# This is a BitKeeper generated diff -Nru style patch.
#
# ChangeSet
#   2004/02/28 07:58:28-08:00 viro@parcelfarce.linux.theplanet.co.uk 
#   [PATCH] oops on HPFS filesystem file rename
#   
#   Maurice van der Stee noted that he got an oops on a HPFS filesystem when
#   saving an edited file..
#   
#     <stares at the code>
#     <blinks>
#     <wonders whereTF do we assign hpfs1_i and hpfs2_i if both inodes are non-NULL>
#     <finds the patch in question>
#     <stares at jgarzik>
#   
#   This fixes it.  That, BTW, means that *nobody* had ever tried to use
#   hpfs r/w since 2.5.3-pre3.
# 
# fs/hpfs/buffer.c
#   2004/02/27 22:33:29-08:00 viro@parcelfarce.linux.theplanet.co.uk +14 -42
#   oops on HPFS filesystem file rename
# 
# ChangeSet
#   2004/02/28 07:54:20-08:00 bunk@fs.tum.de 
#   [PATCH] move rme96xx to Documentation/sound/oss/
#   
#   From Hans Ulrich Niedermann
#   
#   All sound documentation with the exception of the OSS rme96xx
#   documentation is under Documentation/sound/{alsa,oss}.
#   
#   Move the rme966xx docs, and fix the Kconfig comments
# 
# sound/oss/Kconfig
#   2004/01/13 12:23:01-08:00 bunk@fs.tum.de +1 -1
#   move rme96xx to Documentation/sound/oss/
# 
# Documentation/sound/oss/rme96xx
#   2004/02/28 07:50:54-08:00 torvalds@ppc970.osdl.org +0 -0
#   Rename: Documentation/sound/rme96xx -> Documentation/sound/oss/rme96xx
# 
# ChangeSet
#   2004/02/28 07:50:29-08:00 phil.el@wanadoo.fr 
#   [PATCH] oprofile needs smp_num_siblings on x86-64
#   
#   P4 oprofile needs cpu_sibling_map and smp_num_siblings, the later
#   was not exported
# 
# arch/x86_64/kernel/x8664_ksyms.c
#   2004/02/27 22:10:55-08:00 phil.el@wanadoo.fr +1 -0
#   oprofile needs smp_num_siblings on x86-64
# 
# ChangeSet
#   2004/02/28 07:48:48-08:00 olof@austin.ibm.com 
#   [PATCH] ppc64: Use iommu=force instead of iommu=on for commonality with x86_64
# 
# arch/ppc64/kernel/prom.c
#   2004/02/28 00:27:02-08:00 olof@austin.ibm.com +1 -1
#   ppc64: Use iommu=force instead of iommu=on for commonality with x86_64
# 
# ChangeSet
#   2004/02/28 02:02:53-08:00 davidm@tiger.hpl.hp.com 
#   ia64: Fix pdflush-triggered stack-overflow due to long thread-creation chains.
#   
#   The pdflush kernel threads can lead to an unbounded chain of thread-creations
#   which can overflow the kernel stacks because we didn't uses to reset
#   the stack on kernel thread-creation.  We do now.
#   
#   Reported by Andreas Schwab, tracked down with help from Keith Owens.
# 
# arch/ia64/kernel/process.c
#   2004/02/28 02:02:47-08:00 davidm@tiger.hpl.hp.com +49 -37
#   (copy_thread): Reset the stack to the beginning.  This prevents stack-
#   	overflows for poorly written kernel threads which cause an
#   	(unbounded) chain of thread creations as is currentl the case
#   	for the pdflush threads.
#   (kernel_thread): Directly setup a call to do_fork(), bypassing the system-
#   	call and simultaneously resetting the stack to the beginning.
#   (kernel_thread_helper): New function.
# 
# arch/ia64/kernel/head.S
#   2004/02/28 02:02:47-08:00 davidm@tiger.hpl.hp.com +13 -0
#   (ia64_invoke_kernel_thread_helper): New routine.
# 
# ChangeSet
#   2004/02/27 21:45:51-08:00 peterc@gelato.unsw.edu.au 
#   [PATCH] ia64: greatly speed-up I/O-SAPIC irq_enable()/irq_disable()
#   
#   This patch changes the I/O SAPIC code to cache the low 32 bits of the mask
#   word in kernel memory.  This greatly speeds up mask_irq() and unmask_irq().
#   
#   Normally, these operations are not on the speed-critical path of the
#   kernel but with certain devices drivers (including users-level device-
#   drivers) they can become performance-critical.
# 
# include/asm-ia64/iosapic.h
#   2004/02/27 03:39:17-08:00 peterc@gelato.unsw.edu.au +2 -2
#   ia64: greatly speed-up I/O-SAPIC irq_enable()/irq_disable()
# 
# arch/ia64/kernel/iosapic.c
#   2004/02/27 03:39:48-08:00 peterc@gelato.unsw.edu.au +8 -8
#   ia64: greatly speed-up I/O-SAPIC irq_enable()/irq_disable()
# 
# ChangeSet
#   2004/02/27 21:39:54-08:00 eranian@hpl.hp.com 
#   [PATCH] ia64: perfmon update
#   
#           - fix bug in pfm_unload(), not allowed when not on correct CPU for
#             system-wide
#           - some perf/cleanup in overflow handler
#           - fix reset_pmds to be on a per PMD basis on counter overflow rather
#             than global
#           - remove timing debug code on messages
#           - no kernel info leak on PFM_END_MSG
#           - remove double-store on reg_flags for pfm_write_pmcs, pfm_write_pmds
#           - on restart reset_pmds is 0 by default
#           - cleanup useless macros
#           - cleanup some debug prints
#           - added ability to remove debug code
#           - streamlined sys_perfmonctl(), pfm_read_pmds(), pfm_write_*()
#           - added current->tgid to default format sample header by using one
#             reserved field
# 
# include/asm-ia64/perfmon_default_smpl.h
#   2004/02/26 09:25:52-08:00 eranian@hpl.hp.com +2 -2
#   ia64: perfmon update
# 
# arch/ia64/kernel/perfmon_default_smpl.c
#   2004/02/26 09:26:27-08:00 eranian@hpl.hp.com +1 -0
#   ia64: perfmon update
# 
# arch/ia64/kernel/perfmon.c
#   2004/02/27 08:40:40-08:00 eranian@hpl.hp.com +180 -177
#   ia64: perfmon update
# 
# ChangeSet
#   2004/02/27 21:17:14-08:00 davidm@tiger.hpl.hp.com 
#   ia64: Fix IDE block-layer BUG_ON() reported by Darren Williams.
#   
#   The problem was that IDE-disks on machines with IDE harddisks,
#   memory above 4GB and no hardware I/O TLB would go BUG_ON() in
#   blk_queue_bounce_limit() because the IDE-controller could only
#   address 4GB of memory and that was much less than BLK_BOUNCE_ISA
#   (which is equal to ISA_DMA_THRESHOLD).  Note that the problem does
#   NOT trigger with CD-ROMs, which always uses the software I/O TLB
#   (and hence bounce-buffers) on such machines.
#   
#   The best fix seems to be to simply lower ISA_DMA_THRESHOLD to 4GB-1 since
#   that will ensure that the IDE block layer allocates memory with GFP_DMA,
#   which will minimize bounce buffering.
# 
# include/asm-ia64/scatterlist.h
#   2004/02/27 21:17:07-08:00 davidm@tiger.hpl.hp.com +10 -2
#   (ISA_DMA_THRESHOLD): Lower from 0xffffffffffffffff to 0xffffffff so it
#   	matches the max. physical address returned for GFP_DMA allocations
#   	on platforms which don't have a hardware I/O MMU.
# 
# ChangeSet
#   2004/02/27 17:23:31-08:00 olof@austin.ibm.com 
#   [PATCH] ppc64: Add iommu=on for enabling DART on small-mem machines
#   
#   This makes it possible for people like me with a small-mem G5 to enable
#   the DART.  I see two reasons for wanting to do so:
#   
#   1. To debug/test DART/iommu code itself (small audience, including
#      myself).
#   2. To debug drivers on small-mem machines, since bad pci_map*() usage will
#      be punished (possibly larger audience).
# 
# arch/ppc64/kernel/prom.c
#   2004/02/27 07:48:10-08:00 olof@austin.ibm.com +10 -3
#   ppc64: Add iommu=on for enabling DART on small-mem machines
# 
# ChangeSet
#   2004/02/27 17:22:53-08:00 torvalds@ppc970.osdl.org 
#   Merge bk://kernel.bkbits.net/gregkh/linux/pci-2.6
#   into ppc970.osdl.org:/home/torvalds/v2.5/linux
# 
# drivers/pci/hotplug/rpaphp_core.c
#   2004/02/27 17:22:51-08:00 torvalds@ppc970.osdl.org +0 -1
#   Auto merged
# 
# drivers/pci/hotplug/rpaphp.h
#   2004/02/27 17:22:51-08:00 torvalds@ppc970.osdl.org +0 -1
#   Auto merged
# 
# drivers/pci/hotplug/Kconfig
#   2004/02/27 17:22:51-08:00 torvalds@ppc970.osdl.org +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/27 17:22:02-08:00 chip@pobox.com 
#   [PATCH] export locks_remove_posix
#   
#   kNFSd needs it.
# 
# fs/locks.c
#   2004/02/27 16:44:02-08:00 chip@pobox.com +2 -0
#   export locks_remove_posix
# 
# ChangeSet
#   2004/02/27 17:13:54-08: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/irq.c
#   2004/02/27 17:13:48-08:00 davidm@tiger.hpl.hp.com +0 -0
#   Auto merged
# 
# arch/ia64/Kconfig
#   2004/02/27 17:13:47-08:00 davidm@tiger.hpl.hp.com +0 -0
#   Auto merged
# 
# ChangeSet
#   2004/02/27 15:07:27-08:00 kenneth.w.chen@intel.com 
#   [PATCH] ia64: move irq_entry()/irq_exit() to ia64_handle_irq()
#   
#   This patch fixes a bug which could cause do_softirq() to be called
#   at the wrong time (from do_IRQ()) or without pre-emption protection.
# 
# arch/ia64/kernel/irq_ia64.c
#   2004/02/26 14:13:14-08:00 kenneth.w.chen@intel.com +2 -2
#   ia64: move irq_entry()/irq_exit() to ia64_handle_irq()
# 
# arch/ia64/kernel/irq.c
#   2004/02/26 14:13:11-08:00 kenneth.w.chen@intel.com +0 -2
#   ia64: move irq_entry()/irq_exit() to ia64_handle_irq()
# 
# ChangeSet
#   2004/02/27 22:45:22+00:00 rmk@flint.arm.linux.org.uk 
#   [MTD] Update integrator-flash.c with MTD CVS.
#   
#   Allow command line partitioning for use with Integrator flash.
# 
# drivers/mtd/maps/integrator-flash.c
#   2004/02/27 22:43:16+00:00 rmk@flint.arm.linux.org.uk +4 -3
#   Allow command line partitioning for use with Integrator flash.
#   Sync with MTD CVS.
# 
# ChangeSet
#   2004/02/27 22:14:34+00:00 rmk@flint.arm.linux.org.uk 
#   [MTD] Fix ARM Firmware Suite MTD partition detection.
#   
#   Tighten AFS partition checks:
#   - check footer checksum.
#   - check that the image name is NUL terminated.
#   - return error from mtd->read intact.
#   This prevents us finding bogus AFS partitions.
# 
# drivers/mtd/afs.c
#   2004/02/27 22:12:51+00:00 rmk@flint.arm.linux.org.uk +45 -5
#   Tighten AFS partition checks:
#   - check footer checksum.
#   - check that the image name is NUL terminated.
#   - return error from mtd->read intact.
#   This prevents us finding bogus AFS partitions.
# 
# ChangeSet
#   2004/02/27 21:52:15+00:00 rmk@flint.arm.linux.org.uk 
#   [ARM] Fix SA1111 OHCI IRQ handler return type.
# 
# drivers/usb/host/ohci-sa1111.c
#   2004/02/27 21:50:27+00:00 rmk@flint.arm.linux.org.uk +2 -2
#   IRQ handlers return irqreturn_t.
# 
# ChangeSet
#   2004/02/27 21:18:15+00:00 rmk@flint.arm.linux.org.uk 
#   [MTD] Fix build errors in Lubbock MTD map driver.
# 
# drivers/mtd/maps/lubbock-flash.c
#   2004/02/27 21:11:47+00:00 rmk@flint.arm.linux.org.uk +3 -3
#   Fix build errors:
#   lubbock-flash.c: In function `init_lubbock':
#   lubbock-flash.c:77: error: too few arguments to function `__ioremap'
#   lubbock-flash.c:101: warning: ISO C90 forbids mixed declarations and code
# 
# ChangeSet
#   2004/02/27 10:41:00-08:00 kenneth.w.chen@intel.com 
#   [PATCH] ia64: make hugetlbfs page size a boot-time option
#   
#   This patch makes it possible to select the hugetlbfs page size at boot-time,
#   rather than at compile-time.  We believe we have resolved all the remaining
#   issues.  All critical speed path has been taken care of, i.e., vhpt handler
#   and context switch.  There should be no performance penalty with this dynamic
#   hugetlb page size feature.
#   
#   We would like to thank Jack Steiner for his initiative on this feature
#   and his initial cool working patch.
# 
# include/asm-ia64/page.h
#   2004/02/26 12:18:51-08:00 kenneth.w.chen@intel.com +8 -24
#   ia64: make hugetlbfs page size a boot-time option
# 
# include/asm-ia64/mmu_context.h
#   2004/02/26 12:18:51-08:00 kenneth.w.chen@intel.com +3 -2
#   ia64: make hugetlbfs page size a boot-time option
# 
# arch/ia64/mm/init.c
#   2004/02/26 12:18:51-08:00 kenneth.w.chen@intel.com +4 -0
#   ia64: make hugetlbfs page size a boot-time option
# 
# arch/ia64/mm/hugetlbpage.c
#   2004/02/26 12:18:51-08:00 kenneth.w.chen@intel.com +37 -5
#   ia64: make hugetlbfs page size a boot-time option
# 
# arch/ia64/kernel/ivt.S
#   2004/02/26 12:18:51-08:00 kenneth.w.chen@intel.com +3 -2
#   ia64: make hugetlbfs page size a boot-time option
# 
# arch/ia64/Kconfig
#   2004/02/26 12:18:51-08:00 kenneth.w.chen@intel.com +0 -33
#   ia64: make hugetlbfs page size a boot-time option
# 
# ChangeSet
#   2004/02/24 14:04:40-08:00 greg@kroah.com 
#   PCI Hotplug: clean up the Makefile a bit more.
#   
#   Still need to fix up the pcie and shpc options to be saner for distros to use.
# 
# drivers/pci/hotplug/Makefile
#   2004/02/24 06:04:19-08:00 greg@kroah.com +8 -10
#   PCI Hotplug: clean up the Makefile a bit more.
#   
#   Still need to fix up the pcie and shpc options to be saner for distros to use.
# 
# ChangeSet
#   2004/02/24 14:02:08-08:00 greg@kroah.com 
#   PCI Hotplug: remove unneeded ACPI Makefile rules.
# 
# drivers/pci/hotplug/Makefile
#   2004/02/24 06:01:25-08:00 greg@kroah.com +5 -14
#   PCI Hotplug: remove unneeded ACPI Makefile rules.
# 
# ChangeSet
#   2004/02/24 11:08:29-08:00 dlsy@snoqualmie.dp.intel.com 
#   [PATCH] PCI Hotplug: Patch to get polling mode in SHPC hot-plug driver properly working
#   
#   Here is the patch to get polling mode in SHPC hot-plug properly
#   working.
# 
# drivers/pci/hotplug/shpchp_hpc.c
#   2004/02/23 14:45:31-08:00 dlsy@snoqualmie.dp.intel.com +29 -20
#   PCI Hotplug: Patch to get polling mode in SHPC hot-plug driver properly working
# 
# drivers/pci/hotplug/shpchp_ctrl.c
#   2004/02/23 14:45:31-08:00 dlsy@snoqualmie.dp.intel.com +2 -0
#   PCI Hotplug: Patch to get polling mode in SHPC hot-plug driver properly working
# 
# drivers/pci/hotplug/shpchp.h
#   2004/02/23 14:53:13-08:00 dlsy@snoqualmie.dp.intel.com +2 -2
#   PCI Hotplug: Patch to get polling mode in SHPC hot-plug driver properly working
# 
# drivers/pci/hotplug/pciehp_ctrl.c
#   2004/02/23 14:45:31-08:00 dlsy@snoqualmie.dp.intel.com +2 -0
#   PCI Hotplug: Patch to get polling mode in SHPC hot-plug driver properly working
# 
# ChangeSet
#   2004/02/24 11:08:13-08:00 lxiep@ltcfwd.linux.ibm.com 
#   [PATCH] PCI Hotplug: fix rpaphp bugs
#   
#   The attached patch has a fix for the conflict between  fakephp and
#   rpaphp so that fakephp and rpaphp can't be built into the kernel at the
#   same time and a couple of  problems I missed in my previous patch.
#   (Sorry about that).
# 
# drivers/pci/hotplug/rpaphp_core.c
#   2004/02/20 04:16:33-08:00 lxiep@ltcfwd.linux.ibm.com +1 -3
#   PCI Hotplug: fix rpaphp bugs
# 
# drivers/pci/hotplug/rpaphp.h
#   2004/02/20 04:16:33-08:00 lxiep@ltcfwd.linux.ibm.com +1 -1
#   PCI Hotplug: fix rpaphp bugs
# 
# drivers/pci/hotplug/Kconfig
#   2004/02/20 04:16:33-08:00 lxiep@ltcfwd.linux.ibm.com +1 -1
#   PCI Hotplug: fix rpaphp bugs
# 
# ChangeSet
#   2004/02/24 11:07:59-08:00 rmk-pci@arm.linux.org.uk 
#   [PATCH] PCI: Introduce bus->bridge_ctl member
#   
#   GregKH mentioned confirmed that people have been waiting for this patch.
#   Appologies, it had completely evaporated from my mind.
#   
#   This patch introduces the "bridge_ctl" member of pci_bus, which allows
#   architectures to tweak the bridge control register (eg, for setting
#   fast back to back modes etc) in pcibios_fixup_bus().
#   
#   Please note, though, that the value is only written back if
#   pci_setup_bridge() is called.  This will be called if an architecture
#   is using the generic PCI bus setup functionality in setup-bus.c.
#   If an architecture doesn't, then it is the responsibility of the
#   architecture to write this value to the bridge as appropriate.
#   
#   (That said, the bridge control register is only ever changed if an
#   architecture is using setup-bus.c anyway, so there should be no
#   overall functional change.)
# 
# include/linux/pci.h
#   2004/02/18 15:41:55-08:00 rmk-pci@arm.linux.org.uk +2 -0
#   PCI: Introduce bus->bridge_ctl member
# 
# drivers/pci/setup-bus.c
#   2003/11/24 02:33:06-08:00 rmk-pci@arm.linux.org.uk +10 -12
#   PCI: Introduce bus->bridge_ctl member
# 
# drivers/pci/probe.c
#   2004/02/18 14:41:09-08:00 rmk-pci@arm.linux.org.uk +4 -0
#   PCI: Introduce bus->bridge_ctl member
# 
# ChangeSet
#   2004/02/24 11:07:43-08:00 rmk-pci@arm.linux.org.uk 
#   [PATCH] PCI: Don't report pci_request_regions() failure twice
#   
#   pci_request_regions() reports an error when pci_request_region() fails.
#   However, since pci_request_region() already reports an error on failure,
#   pci_request_regions() has some unwanted duplication.
# 
# drivers/pci/pci.c
#   2004/02/20 12:00:29-08:00 rmk-pci@arm.linux.org.uk +0 -5
#   PCI: Don't report pci_request_regions() failure twice
# 
# ChangeSet
#   2004/02/24 11:07:29-08:00 rmk-pci@arm.linux.org.uk 
#   [PATCH] PCI: Report meaningful error for failed resource allocation
#   
#   pci_assign_resource reports odd messages when resource allocation fails.
#   This is because res->end and res->start are modified by allocate_resource.
#   For example:
#   
#   PCI: Failed to allocate resource 1(0-ffffffff) for 0000:00:01.0
#   
#   The following patch reports whether it's an IO or memory resource, and
#   includes the correct size.  For consistency, we report it in a similar
#   way to the failure message in pci_request_region(), even though
#   res->start is unlikely to be useful.
# 
# drivers/pci/setup-res.c
#   2004/02/20 11:58:19-08:00 rmk-pci@arm.linux.org.uk +3 -2
#   PCI: Report meaningful error for failed resource allocation
# 
diff -Nru a/Documentation/sound/oss/rme96xx b/Documentation/sound/oss/rme96xx
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/Documentation/sound/oss/rme96xx	Sun Feb 29 12:54:28 2004
@@ -0,0 +1,767 @@
+Beta release of the rme96xx (driver for RME 96XX cards like the 
+"Hammerfall" and the "Hammerfall light") 
+
+Important: The driver module has to be installed on a freshly rebooted system, 
+otherwise the driver might not be able to acquire its buffers.
+
+features:
+
+ - OSS programming interface (i.e. runs with standard OSS soundsoftware) 
+ - OSS/Multichannel interface (OSS multichannel is done by just aquiring
+   more than 2 channels). The driver does not use more than one device 
+   ( yet .. this feature may be implemented later ) 
+ - more than one RME card supported
+
+The driver uses a specific multichannel interface, which I will document
+when the driver gets stable. (take a look at the defines in rme96xx.h,
+which adds blocked multichannel formats i.e instead of 
+lrlrlrlr --> llllrrrr  etc.
+
+Use the "rmectrl" programm to look at the status of the card .. 
+or use xrmectrl, a GUI interface for the ctrl program.
+
+What you can do with the rmectrl program is to set the stereo device for
+OSS emulation (e.g. if you use SPDIF out).
+
+You do:
+
+./ctrl offset 24 24
+
+which makes the stereo device use channels 25 and 26.
+
+Guenter Geiger <geiger@epy.co.at>
+
+copy the first part of the attached source code into rmectrl.c
+and the  second part into xrmectrl (or get the program from
+http://gige.xdv.org/pages/soft/pages/rme)
+
+to compile: gcc -o rmectrl rmectrl.c
+------------------------------ snip ------------------------------------
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/ioctl.h>
+#include <fcntl.h>
+#include <linux/soundcard.h>
+#include <math.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "rme96xx.h"
+
+/*
+  remctrl.c
+  (C) 2000 Guenter Geiger <geiger@debian.org>
+  HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
+*/
+
+/* # define DEVICE_NAME "/dev/mixer" */
+# define DEVICE_NAME "/dev/mixer1"
+
+
+void usage(void)
+{
+     fprintf(stderr,"usage: rmectrl [/dev/mixer<n>] [command [options]]\n\n");
+     fprintf(stderr,"where command is one of:\n");
+     fprintf(stderr,"  help                       show this help\n");
+     fprintf(stderr,"  status                     show status bits\n");
+     fprintf(stderr,"  control                    show control bits\n");
+     fprintf(stderr,"  mix                        show mixer/offset status\n");
+     fprintf(stderr,"  master <n>                 set sync master\n");
+     fprintf(stderr,"  pro <n>                    set spdif out pro\n");
+     fprintf(stderr,"  emphasis <n>               set spdif out emphasis\n");
+     fprintf(stderr,"  dolby <n>                  set spdif out no audio\n");
+     fprintf(stderr,"  optout <n>                 set spdif out optical\n");
+     fprintf(stderr,"  wordclock <n>              set sync wordclock\n");
+     fprintf(stderr,"  spdifin <n>                set spdif in (0=optical,1=coax,2=intern)\n");
+     fprintf(stderr,"  syncref <n>                set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n");
+     fprintf(stderr,"  adat1cd <n>                set ADAT1 on internal CD\n");
+     fprintf(stderr,"  offset <devnr> <in> <out>  set dev (0..3) offset (0..25)\n");
+     exit(-1);
+}
+
+
+int main(int argc, char* argv[])
+{
+     int cards;
+     int ret;
+     int i;
+     double ft;
+     int fd, fdwr;
+     int param,orig;
+     rme_status_t stat;
+     rme_ctrl_t ctrl;
+     char *device;
+     int argidx;
+
+     if (argc < 2)
+	  usage();
+
+     if (*argv[1]=='/') {
+	  device = argv[1];
+	  argidx = 2;
+     }
+     else {
+	  device = DEVICE_NAME;
+	  argidx = 1;
+     }
+
+     fprintf(stdout,"mixer device %s\n",device);
+     if ((fd = open(device,O_RDONLY)) < 0) {
+	  fprintf(stdout,"opening device failed\n");
+	  exit(-1);
+     }
+
+     if ((fdwr = open(device,O_WRONLY)) < 0) {
+	  fprintf(stdout,"opening device failed\n");
+	  exit(-1);
+     }
+
+     if (argc < argidx+1)
+	  usage();
+
+     if (!strcmp(argv[argidx],"help"))
+        usage();
+     if (!strcmp(argv[argidx],"-h"))
+        usage();
+     if (!strcmp(argv[argidx],"--help"))
+        usage();
+
+     if (!strcmp(argv[argidx],"status")) {
+	  ioctl(fd,SOUND_MIXER_PRIVATE2,&stat);
+	  fprintf(stdout,"stat.irq %d\n",stat.irq);
+	  fprintf(stdout,"stat.lockmask %d\n",stat.lockmask);
+	  fprintf(stdout,"stat.sr48 %d\n",stat.sr48);
+	  fprintf(stdout,"stat.wclock %d\n",stat.wclock);
+	  fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint);
+	  fprintf(stdout,"stat.syncmask %d\n",stat.syncmask);
+	  fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed);
+	  fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy);
+	  fprintf(stdout,"stat.tc_out %d\n",stat.tc_out);
+	  fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate);
+	  fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error);
+	  fprintf(stdout,"stat.bufid %d\n",stat.bufid);
+	  fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"control")) {
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  fprintf(stdout,"ctrl.start %d\n",ctrl.start);
+	  fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency);
+	  fprintf(stdout,"ctrl.master %d\n",ctrl.master);
+	  fprintf(stdout,"ctrl.ie %d\n",ctrl.ie);
+	  fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48);
+	  fprintf(stdout,"ctrl.spare %d\n",ctrl.spare);
+	  fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed);
+	  fprintf(stdout,"ctrl.pro %d\n",ctrl.pro);
+	  fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis);
+	  fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby);
+	  fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out);
+	  fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock);
+	  fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in);
+	  fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref);
+	  fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset);
+	  fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select);
+	  fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock);
+	  fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write);
+	  fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"mix")) {
+	  rme_mixer mix;
+	  int i;
+
+	  for (i=0; i<4; i++) {
+	       mix.devnr = i;
+	       ioctl(fd,SOUND_MIXER_PRIVATE1,&mix);
+	       if (mix.devnr == i) {
+		    fprintf(stdout,"devnr %d\n",mix.devnr);
+		    fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset);
+		    fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset);
+	       }
+	  }
+	  exit (0);
+     }
+
+/* the control flags */
+
+     if (argc < argidx+2)
+	  usage();
+
+     if (!strcmp(argv[argidx],"master")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("master = %d\n",val);
+	  ctrl.master = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"pro")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("pro = %d\n",val);
+	  ctrl.pro = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"emphasis")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("emphasis = %d\n",val);
+	  ctrl.emphasis = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"dolby")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("dolby = %d\n",val);
+	  ctrl.dolby = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"optout")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("optout = %d\n",val);
+	  ctrl.opt_out = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"wordclock")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("wordclock = %d\n",val);
+	  ctrl.wordclock = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"spdifin")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("spdifin = %d\n",val);
+	  ctrl.spdif_in = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"syncref")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("syncref = %d\n",val);
+	  ctrl.sync_ref = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+     if (!strcmp(argv[argidx],"adat1cd")) {
+	  int val = atoi(argv[argidx+1]);
+	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
+	  printf("adat1cd = %d\n",val);
+	  ctrl.adat1_cd = val;
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
+	  exit (0);
+     }
+
+/* setting offset */
+
+     if (argc < argidx+4)
+	  usage();
+
+     if (!strcmp(argv[argidx],"offset")) {
+	  rme_mixer mix;
+
+	  mix.devnr = atoi(argv[argidx+1]);
+
+	  mix.i_offset = atoi(argv[argidx+2]);
+	  mix.o_offset = atoi(argv[argidx+3]);
+	  ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix);
+	  fprintf(stdout,"devnr %d\n",mix.devnr);
+	  fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset);
+	  fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset);
+	  exit (0);
+     }
+
+     usage();
+     exit (0); /* to avoid warning */
+}
+
+
+---------------------------- <snip> --------------------------------
+#!/usr/bin/wish
+
+# xrmectrl
+# (C) 2000 Guenter Geiger <geiger@debian.org>
+# HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
+
+#set defaults "-relief ridged"
+set CTRLPROG "./rmectrl"
+if {$argc} {
+    set CTRLPROG "$CTRLPROG $argv"
+}
+puts "CTRLPROG $CTRLPROG"
+
+frame .butts
+button .butts.exit -text "Exit" -command "exit" -relief ridge
+#button .butts.state -text "State" -command "get_all"
+
+pack .butts.exit -side left
+pack .butts -side bottom
+
+
+#
+# STATUS
+#
+
+frame .status
+
+# Sampling Rate
+
+frame .status.sr
+label .status.sr.text -text "Sampling Rate" -justify left
+radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times
+radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times
+radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times
+radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw  -variable srate -value 96000 -font times
+
+pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3
+
+# Lock
+
+frame .status.lock
+label .status.lock.text -text "Lock" -justify left
+checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times
+checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times
+checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times
+
+pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3 
+
+# Sync
+
+frame .status.sync
+label .status.sync.text -text "Sync" -justify left
+checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times
+checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times
+checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times
+
+pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3 
+
+# Timecode
+
+frame .status.tc
+label .status.tc.text -text "Timecode" -justify left
+checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times
+checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times
+checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times
+
+pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3 
+
+# SPDIF In
+
+frame .status.spdif
+label .status.spdif.text -text "SPDIF In" -justify left
+label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times
+checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times
+
+pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3 
+
+pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1
+
+
+#
+# CONTROL 
+#
+
+proc setprof {} {
+    global CTRLPROG
+    global spprof
+    exec $CTRLPROG pro $spprof
+}
+
+proc setemph {} {
+    global CTRLPROG
+    global spemph
+    exec $CTRLPROG emphasis $spemph
+}
+
+proc setnoaud {} {
+    global CTRLPROG
+    global spnoaud
+    exec $CTRLPROG dolby $spnoaud
+}
+
+proc setoptical {} {
+    global CTRLPROG
+    global spoptical
+    exec $CTRLPROG optout $spoptical
+}
+
+proc setspdifin {} {
+    global CTRLPROG
+    global spdifin
+    exec $CTRLPROG spdifin [expr $spdifin - 1]
+}
+
+proc setsyncsource {} {
+    global CTRLPROG
+    global syncsource
+    exec $CTRLPROG syncref [expr $syncsource -1]
+}
+
+
+proc setmaster {} {
+    global CTRLPROG
+    global master
+    exec $CTRLPROG master $master
+}
+
+proc setwordclock {} {
+    global CTRLPROG
+    global wordclock
+    exec $CTRLPROG wordclock $wordclock
+}
+
+proc setadat1cd {} {
+    global CTRLPROG
+    global adat1cd
+    exec $CTRLPROG adat1cd $adat1cd
+}
+
+
+frame .control
+
+# SPDIF In & SPDIF Out
+
+
+frame .control.spdif
+
+frame .control.spdif.in
+label .control.spdif.in.text -text "SPDIF In" -justify left
+radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times
+radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times
+radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times
+
+checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times
+
+pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd
+
+label .control.spdif.space
+
+frame .control.spdif.out
+label .control.spdif.out.text -text "SPDIF Out" -justify left
+checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times
+checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times
+checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times
+checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times
+
+pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom
+
+pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1
+
+# Sync Mode & Sync Source
+
+frame .control.sync
+frame .control.sync.mode
+label .control.sync.mode.text -text "Sync Mode" -justify left
+checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times
+checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times
+
+pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc
+
+label .control.sync.space
+
+frame .control.sync.src
+label .control.sync.src.text -text "Sync Source" -justify left
+radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times
+radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times
+radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times
+radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times
+
+pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom
+
+pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1
+
+label .control.space -text "" -width 10
+
+# Buffer Size
+
+frame .control.buf
+label .control.buf.text -text "Buffer Size (Latency)" -justify left
+radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times
+radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times
+radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times
+radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times
+radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times
+radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times
+radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times
+radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times
+
+pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3 
+
+# Offset
+
+frame .control.offset
+
+frame .control.offset.in
+label .control.offset.in.text -text "Offset In" -justify left
+label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
+label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
+label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
+label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
+
+pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3
+
+label .control.offset.space
+
+frame .control.offset.out
+label .control.offset.out.text -text "Offset Out" -justify left
+label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
+label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
+label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
+label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
+
+pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom
+
+pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1
+
+
+pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1
+
+
+label .statustext -text Status -justify center -relief ridge
+label .controltext -text Control -justify center -relief ridge
+
+label .statusspace
+label .controlspace
+
+pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1
+
+
+proc get_bit {output sstr} {
+    set idx1 [string last [concat $sstr 1] $output]
+    set idx1 [expr $idx1 != -1]
+    return $idx1
+}
+
+proc get_val {output sstr} {
+    set val [string wordend $output [string last $sstr $output]] 
+    set val [string range $output $val [expr $val+1]]
+    return $val
+}
+
+proc get_val2 {output sstr} {
+    set val [string wordend $output [string first $sstr $output]] 
+    set val [string range $output $val [expr $val+2]]
+    return $val
+}
+
+proc get_control {} {
+    global spprof
+    global spemph
+    global spnoaud
+    global spoptical
+    global spdifin
+    global ssrate
+    global master
+    global wordclock
+    global syncsource
+    global CTRLPROG
+
+    set f [open "| $CTRLPROG control" r+]
+    set ooo [read $f 1000]
+    close $f
+#    puts $ooo
+
+    set spprof [ get_bit $ooo "pro"]
+    set spemph [ get_bit $ooo "emphasis"]
+    set spnoaud [ get_bit $ooo "dolby"]
+    set spoptical [ get_bit $ooo "opt_out"]
+    set spdifin [ expr [ get_val $ooo "spdif_in"] + 1]
+    set ssrate [ expr [ get_val $ooo "latency"] + 1]
+    set master [ expr [ get_val $ooo "master"]]
+    set wordclock [ expr [ get_val $ooo "wordclock"]]
+    set syncsource [ expr [ get_val $ooo "sync_ref"] + 1]
+}
+
+proc get_status {} {
+    global srate
+    global ctrlcom
+
+    global adatlock1
+    global adatlock2
+    global adatlock3
+
+    global adatsync1
+    global adatsync2
+    global adatsync3
+
+    global tcbusy
+    global tcout
+    global tcvalid
+
+    global spdiferr
+    global crystal
+    global .status.spdif.text
+    global CTRLPROG
+
+
+    set f [open "| $CTRLPROG status" r+]
+    set ooo [read $f 1000]
+    close $f
+#    puts $ooo
+
+# samplerate
+
+    set idx1 [string last "sr48 1" $ooo]
+    set idx2 [string last "doublespeed 1" $ooo]
+    if {$idx1 >= 0} {
+	set fact1 48000
+    } else {
+	set fact1 44100
+    }
+
+    if {$idx2 >= 0} {
+	set fact2 2
+    } else {
+	set fact2 1
+    }
+    set srate [expr $fact1 * $fact2]
+#   ADAT lock
+
+    set val [get_val $ooo lockmask]
+    set adatlock1 0
+    set adatlock2 0
+    set adatlock3 0
+    if {[expr $val & 1]} {
+       set adatlock3 1
+    }
+    if {[expr $val & 2]} {
+       set adatlock2 1
+    }
+    if {[expr $val & 4]} {
+       set adatlock1 1
+    }
+
+#  ADAT sync
+    set val [get_val $ooo syncmask]
+    set adatsync1 0
+    set adatsync2 0
+    set adatsync3 0
+
+    if {[expr $val & 1]} {
+       set adatsync3 1
+    }
+    if {[expr $val & 2]} {
+       set adatsync2 1
+    }
+    if {[expr $val & 4]} {
+       set adatsync1 1
+    }
+
+# TC busy
+
+    set tcbusy [get_bit $ooo "busy"]
+    set tcout [get_bit $ooo "out"]
+    set tcvalid [get_bit $ooo "valid"]
+    set spdiferr [expr [get_bit $ooo "spdif_error"] == 0]
+
+#  000=64kHz, 100=88.2kHz, 011=96kHz
+#  111=32kHz, 110=44.1kHz, 101=48kHz
+
+    set val [get_val $ooo crystalrate]
+
+    set crystal "--.- kHz"
+    if {$val == 0} {
+        set crystal "64 kHz"
+    }
+    if {$val == 4} {
+        set crystal "88.2 kHz"
+    }
+    if {$val == 3} {
+        set crystal "96 kHz"
+    }
+    if {$val == 7} {
+        set crystal "32 kHz"
+    }
+    if {$val == 6} {
+        set crystal "44.1 kHz"
+    }
+    if {$val == 5} {
+        set crystal "48 kHz"
+    }
+    .status.spdif.sr configure -text $crystal
+}
+
+proc get_offset {} {
+    global inoffset
+    global outoffset
+    global CTRLPROG
+
+    set f [open "| $CTRLPROG mix" r+]
+    set ooo [read $f 1000]
+    close $f
+#    puts $ooo
+
+    if { [string match "*devnr*" $ooo] } {
+	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
+	set val [get_val2 $ooo i_offset]
+	.control.offset.in.off0 configure -text "dev\#0: $val"
+	set val [get_val2 $ooo o_offset]
+	.control.offset.out.off0 configure -text "dev\#0: $val"
+    } else {
+	.control.offset.in.off0 configure -text "dev\#0: -"
+	.control.offset.out.off0 configure -text "dev\#0: -"
+    }
+    if { [string match "*devnr*" $ooo] } {
+	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
+	set val [get_val2 $ooo i_offset]
+	.control.offset.in.off1 configure -text "dev\#1: $val"
+	set val [get_val2 $ooo o_offset]
+	.control.offset.out.off1 configure -text "dev\#1: $val"
+    } else {
+	.control.offset.in.off1 configure -text "dev\#1: -"
+	.control.offset.out.off1 configure -text "dev\#1: -"
+    }
+    if { [string match "*devnr*" $ooo] } {
+	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
+	set val [get_val2 $ooo i_offset]
+	.control.offset.in.off2 configure -text "dev\#2: $val"
+	set val [get_val2 $ooo o_offset]
+	.control.offset.out.off2 configure -text "dev\#2: $val"
+    } else {
+	.control.offset.in.off2 configure -text "dev\#2: -"
+	.control.offset.out.off2 configure -text "dev\#2: -"
+    }
+    if { [string match "*devnr*" $ooo] } {
+	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
+	set val [get_val2 $ooo i_offset]
+	.control.offset.in.off3 configure -text "dev\#3: $val"
+	set val [get_val2 $ooo o_offset]
+	.control.offset.out.off3 configure -text "dev\#3: $val"
+    } else {
+	.control.offset.in.off3 configure -text "dev\#3: -"
+	.control.offset.out.off3 configure -text "dev\#3: -"
+    }
+}
+
+
+proc get_all {} {
+get_status
+get_control
+get_offset
+}
+
+# main
+while {1} {
+  after 200
+  get_all
+  update
+}
diff -Nru a/Documentation/sound/rme96xx b/Documentation/sound/rme96xx
--- a/Documentation/sound/rme96xx	Sun Feb 29 12:54:28 2004
+++ /dev/null	Wed Dec 31 16:00:00 1969
@@ -1,767 +0,0 @@
-Beta release of the rme96xx (driver for RME 96XX cards like the 
-"Hammerfall" and the "Hammerfall light") 
-
-Important: The driver module has to be installed on a freshly rebooted system, 
-otherwise the driver might not be able to acquire its buffers.
-
-features:
-
- - OSS programming interface (i.e. runs with standard OSS soundsoftware) 
- - OSS/Multichannel interface (OSS multichannel is done by just aquiring
-   more than 2 channels). The driver does not use more than one device 
-   ( yet .. this feature may be implemented later ) 
- - more than one RME card supported
-
-The driver uses a specific multichannel interface, which I will document
-when the driver gets stable. (take a look at the defines in rme96xx.h,
-which adds blocked multichannel formats i.e instead of 
-lrlrlrlr --> llllrrrr  etc.
-
-Use the "rmectrl" programm to look at the status of the card .. 
-or use xrmectrl, a GUI interface for the ctrl program.
-
-What you can do with the rmectrl program is to set the stereo device for
-OSS emulation (e.g. if you use SPDIF out).
-
-You do:
-
-./ctrl offset 24 24
-
-which makes the stereo device use channels 25 and 26.
-
-Guenter Geiger <geiger@epy.co.at>
-
-copy the first part of the attached source code into rmectrl.c
-and the  second part into xrmectrl (or get the program from
-http://gige.xdv.org/pages/soft/pages/rme)
-
-to compile: gcc -o rmectrl rmectrl.c
------------------------------- snip ------------------------------------
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <fcntl.h>
-#include <linux/soundcard.h>
-#include <math.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include "rme96xx.h"
-
-/*
-  remctrl.c
-  (C) 2000 Guenter Geiger <geiger@debian.org>
-  HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
-*/
-
-/* # define DEVICE_NAME "/dev/mixer" */
-# define DEVICE_NAME "/dev/mixer1"
-
-
-void usage(void)
-{
-     fprintf(stderr,"usage: rmectrl [/dev/mixer<n>] [command [options]]\n\n");
-     fprintf(stderr,"where command is one of:\n");
-     fprintf(stderr,"  help                       show this help\n");
-     fprintf(stderr,"  status                     show status bits\n");
-     fprintf(stderr,"  control                    show control bits\n");
-     fprintf(stderr,"  mix                        show mixer/offset status\n");
-     fprintf(stderr,"  master <n>                 set sync master\n");
-     fprintf(stderr,"  pro <n>                    set spdif out pro\n");
-     fprintf(stderr,"  emphasis <n>               set spdif out emphasis\n");
-     fprintf(stderr,"  dolby <n>                  set spdif out no audio\n");
-     fprintf(stderr,"  optout <n>                 set spdif out optical\n");
-     fprintf(stderr,"  wordclock <n>              set sync wordclock\n");
-     fprintf(stderr,"  spdifin <n>                set spdif in (0=optical,1=coax,2=intern)\n");
-     fprintf(stderr,"  syncref <n>                set sync source (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n");
-     fprintf(stderr,"  adat1cd <n>                set ADAT1 on internal CD\n");
-     fprintf(stderr,"  offset <devnr> <in> <out>  set dev (0..3) offset (0..25)\n");
-     exit(-1);
-}
-
-
-int main(int argc, char* argv[])
-{
-     int cards;
-     int ret;
-     int i;
-     double ft;
-     int fd, fdwr;
-     int param,orig;
-     rme_status_t stat;
-     rme_ctrl_t ctrl;
-     char *device;
-     int argidx;
-
-     if (argc < 2)
-	  usage();
-
-     if (*argv[1]=='/') {
-	  device = argv[1];
-	  argidx = 2;
-     }
-     else {
-	  device = DEVICE_NAME;
-	  argidx = 1;
-     }
-
-     fprintf(stdout,"mixer device %s\n",device);
-     if ((fd = open(device,O_RDONLY)) < 0) {
-	  fprintf(stdout,"opening device failed\n");
-	  exit(-1);
-     }
-
-     if ((fdwr = open(device,O_WRONLY)) < 0) {
-	  fprintf(stdout,"opening device failed\n");
-	  exit(-1);
-     }
-
-     if (argc < argidx+1)
-	  usage();
-
-     if (!strcmp(argv[argidx],"help"))
-        usage();
-     if (!strcmp(argv[argidx],"-h"))
-        usage();
-     if (!strcmp(argv[argidx],"--help"))
-        usage();
-
-     if (!strcmp(argv[argidx],"status")) {
-	  ioctl(fd,SOUND_MIXER_PRIVATE2,&stat);
-	  fprintf(stdout,"stat.irq %d\n",stat.irq);
-	  fprintf(stdout,"stat.lockmask %d\n",stat.lockmask);
-	  fprintf(stdout,"stat.sr48 %d\n",stat.sr48);
-	  fprintf(stdout,"stat.wclock %d\n",stat.wclock);
-	  fprintf(stdout,"stat.bufpoint %d\n",stat.bufpoint);
-	  fprintf(stdout,"stat.syncmask %d\n",stat.syncmask);
-	  fprintf(stdout,"stat.doublespeed %d\n",stat.doublespeed);
-	  fprintf(stdout,"stat.tc_busy %d\n",stat.tc_busy);
-	  fprintf(stdout,"stat.tc_out %d\n",stat.tc_out);
-	  fprintf(stdout,"stat.crystalrate %d (0=64k 3=96k 4=88.2k 5=48k 6=44.1k 7=32k)\n",stat.crystalrate);
-	  fprintf(stdout,"stat.spdif_error %d\n",stat.spdif_error);
-	  fprintf(stdout,"stat.bufid %d\n",stat.bufid);
-	  fprintf(stdout,"stat.tc_valid %d\n",stat.tc_valid);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"control")) {
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  fprintf(stdout,"ctrl.start %d\n",ctrl.start);
-	  fprintf(stdout,"ctrl.latency %d (0=64 .. 7=8192)\n",ctrl.latency);
-	  fprintf(stdout,"ctrl.master %d\n",ctrl.master);
-	  fprintf(stdout,"ctrl.ie %d\n",ctrl.ie);
-	  fprintf(stdout,"ctrl.sr48 %d\n",ctrl.sr48);
-	  fprintf(stdout,"ctrl.spare %d\n",ctrl.spare);
-	  fprintf(stdout,"ctrl.doublespeed %d\n",ctrl.doublespeed);
-	  fprintf(stdout,"ctrl.pro %d\n",ctrl.pro);
-	  fprintf(stdout,"ctrl.emphasis %d\n",ctrl.emphasis);
-	  fprintf(stdout,"ctrl.dolby %d\n",ctrl.dolby);
-	  fprintf(stdout,"ctrl.opt_out %d\n",ctrl.opt_out);
-	  fprintf(stdout,"ctrl.wordclock %d\n",ctrl.wordclock);
-	  fprintf(stdout,"ctrl.spdif_in %d (0=optical,1=coax,2=intern)\n",ctrl.spdif_in);
-	  fprintf(stdout,"ctrl.sync_ref %d (0=ADAT1,1=ADAT2,2=ADAT3,3=SPDIF)\n",ctrl.sync_ref);
-	  fprintf(stdout,"ctrl.spdif_reset %d\n",ctrl.spdif_reset);
-	  fprintf(stdout,"ctrl.spdif_select %d\n",ctrl.spdif_select);
-	  fprintf(stdout,"ctrl.spdif_clock %d\n",ctrl.spdif_clock);
-	  fprintf(stdout,"ctrl.spdif_write %d\n",ctrl.spdif_write);
-	  fprintf(stdout,"ctrl.adat1_cd %d\n",ctrl.adat1_cd);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"mix")) {
-	  rme_mixer mix;
-	  int i;
-
-	  for (i=0; i<4; i++) {
-	       mix.devnr = i;
-	       ioctl(fd,SOUND_MIXER_PRIVATE1,&mix);
-	       if (mix.devnr == i) {
-		    fprintf(stdout,"devnr %d\n",mix.devnr);
-		    fprintf(stdout,"mix.i_offset %2d (0-25)\n",mix.i_offset);
-		    fprintf(stdout,"mix.o_offset %2d (0-25)\n",mix.o_offset);
-	       }
-	  }
-	  exit (0);
-     }
-
-/* the control flags */
-
-     if (argc < argidx+2)
-	  usage();
-
-     if (!strcmp(argv[argidx],"master")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("master = %d\n",val);
-	  ctrl.master = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"pro")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("pro = %d\n",val);
-	  ctrl.pro = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"emphasis")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("emphasis = %d\n",val);
-	  ctrl.emphasis = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"dolby")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("dolby = %d\n",val);
-	  ctrl.dolby = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"optout")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("optout = %d\n",val);
-	  ctrl.opt_out = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"wordclock")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("wordclock = %d\n",val);
-	  ctrl.wordclock = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"spdifin")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("spdifin = %d\n",val);
-	  ctrl.spdif_in = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"syncref")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("syncref = %d\n",val);
-	  ctrl.sync_ref = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-     if (!strcmp(argv[argidx],"adat1cd")) {
-	  int val = atoi(argv[argidx+1]);
-	  ioctl(fd,SOUND_MIXER_PRIVATE3,&ctrl);
-	  printf("adat1cd = %d\n",val);
-	  ctrl.adat1_cd = val;
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE3,&ctrl);
-	  exit (0);
-     }
-
-/* setting offset */
-
-     if (argc < argidx+4)
-	  usage();
-
-     if (!strcmp(argv[argidx],"offset")) {
-	  rme_mixer mix;
-
-	  mix.devnr = atoi(argv[argidx+1]);
-
-	  mix.i_offset = atoi(argv[argidx+2]);
-	  mix.o_offset = atoi(argv[argidx+3]);
-	  ioctl(fdwr,SOUND_MIXER_PRIVATE1,&mix);
-	  fprintf(stdout,"devnr %d\n",mix.devnr);
-	  fprintf(stdout,"mix.i_offset to %d\n",mix.i_offset);
-	  fprintf(stdout,"mix.o_offset to %d\n",mix.o_offset);
-	  exit (0);
-     }
-
-     usage();
-     exit (0); /* to avoid warning */
-}
-
-
----------------------------- <snip> --------------------------------
-#!/usr/bin/wish
-
-# xrmectrl
-# (C) 2000 Guenter Geiger <geiger@debian.org>
-# HP20020201 - Heiko Purnhagen <purnhage@tnt.uni-hannover.de>
-
-#set defaults "-relief ridged"
-set CTRLPROG "./rmectrl"
-if {$argc} {
-    set CTRLPROG "$CTRLPROG $argv"
-}
-puts "CTRLPROG $CTRLPROG"
-
-frame .butts
-button .butts.exit -text "Exit" -command "exit" -relief ridge
-#button .butts.state -text "State" -command "get_all"
-
-pack .butts.exit -side left
-pack .butts -side bottom
-
-
-#
-# STATUS
-#
-
-frame .status
-
-# Sampling Rate
-
-frame .status.sr
-label .status.sr.text -text "Sampling Rate" -justify left
-radiobutton .status.sr.441 -selectcolor red -text "44.1 kHz" -width 10 -anchor nw -variable srate -value 44100 -font times
-radiobutton .status.sr.480 -selectcolor red -text "48 kHz" -width 10 -anchor nw -variable srate -value 48000 -font times
-radiobutton .status.sr.882 -selectcolor red -text "88.2 kHz" -width 10 -anchor nw -variable srate -value 88200 -font times
-radiobutton .status.sr.960 -selectcolor red -text "96 kHz" -width 10 -anchor nw  -variable srate -value 96000 -font times
-
-pack .status.sr.text .status.sr.441 .status.sr.480 .status.sr.882 .status.sr.960 -side top -padx 3
-
-# Lock
-
-frame .status.lock
-label .status.lock.text -text "Lock" -justify left
-checkbutton .status.lock.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatlock1 -font times
-checkbutton .status.lock.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatlock2 -font times
-checkbutton .status.lock.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatlock3 -font times
-
-pack .status.lock.text .status.lock.adat1 .status.lock.adat2 .status.lock.adat3 -side top -padx 3 
-
-# Sync
-
-frame .status.sync
-label .status.sync.text -text "Sync" -justify left
-checkbutton .status.sync.adat1 -selectcolor red -text "ADAT1" -anchor nw -width 10 -variable adatsync1 -font times
-checkbutton .status.sync.adat2 -selectcolor red -text "ADAT2" -anchor nw -width 10 -variable adatsync2 -font times
-checkbutton .status.sync.adat3 -selectcolor red -text "ADAT3" -anchor nw -width 10 -variable adatsync3 -font times
-
-pack .status.sync.text .status.sync.adat1 .status.sync.adat2 .status.sync.adat3 -side top -padx 3 
-
-# Timecode
-
-frame .status.tc
-label .status.tc.text -text "Timecode" -justify left
-checkbutton .status.tc.busy -selectcolor red -text "busy" -anchor nw -width 10 -variable tcbusy -font times
-checkbutton .status.tc.out -selectcolor red -text "out" -anchor nw -width 10 -variable tcout -font times
-checkbutton .status.tc.valid -selectcolor red -text "valid" -anchor nw -width 10 -variable tcvalid -font times
-
-pack .status.tc.text .status.tc.busy .status.tc.out .status.tc.valid -side top -padx 3 
-
-# SPDIF In
-
-frame .status.spdif
-label .status.spdif.text -text "SPDIF In" -justify left
-label .status.spdif.sr -text "--.- kHz" -anchor n -width 10 -font times
-checkbutton .status.spdif.error -selectcolor red -text "Input Lock" -anchor nw -width 10 -variable spdiferr -font times
-
-pack .status.spdif.text .status.spdif.sr .status.spdif.error -side top -padx 3 
-
-pack .status.sr .status.lock .status.sync .status.tc .status.spdif -side left -fill x -anchor n -expand 1
-
-
-#
-# CONTROL 
-#
-
-proc setprof {} {
-    global CTRLPROG
-    global spprof
-    exec $CTRLPROG pro $spprof
-}
-
-proc setemph {} {
-    global CTRLPROG
-    global spemph
-    exec $CTRLPROG emphasis $spemph
-}
-
-proc setnoaud {} {
-    global CTRLPROG
-    global spnoaud
-    exec $CTRLPROG dolby $spnoaud
-}
-
-proc setoptical {} {
-    global CTRLPROG
-    global spoptical
-    exec $CTRLPROG optout $spoptical
-}
-
-proc setspdifin {} {
-    global CTRLPROG
-    global spdifin
-    exec $CTRLPROG spdifin [expr $spdifin - 1]
-}
-
-proc setsyncsource {} {
-    global CTRLPROG
-    global syncsource
-    exec $CTRLPROG syncref [expr $syncsource -1]
-}
-
-
-proc setmaster {} {
-    global CTRLPROG
-    global master
-    exec $CTRLPROG master $master
-}
-
-proc setwordclock {} {
-    global CTRLPROG
-    global wordclock
-    exec $CTRLPROG wordclock $wordclock
-}
-
-proc setadat1cd {} {
-    global CTRLPROG
-    global adat1cd
-    exec $CTRLPROG adat1cd $adat1cd
-}
-
-
-frame .control
-
-# SPDIF In & SPDIF Out
-
-
-frame .control.spdif
-
-frame .control.spdif.in
-label .control.spdif.in.text -text "SPDIF In" -justify left
-radiobutton .control.spdif.in.input1 -text "Optical" -anchor nw -width 13 -variable spdifin -value 1 -command setspdifin -selectcolor blue -font times
-radiobutton .control.spdif.in.input2 -text "Coaxial" -anchor nw -width 13 -variable spdifin -value 2 -command setspdifin -selectcolor blue -font times
-radiobutton .control.spdif.in.input3 -text "Intern " -anchor nw -width 13 -variable spdifin -command setspdifin -value 3 -selectcolor blue -font times
-
-checkbutton .control.spdif.in.adat1cd -text "ADAT1 Intern" -anchor nw -width 13 -variable adat1cd -command setadat1cd -selectcolor blue -font times
-
-pack .control.spdif.in.text .control.spdif.in.input1 .control.spdif.in.input2 .control.spdif.in.input3 .control.spdif.in.adat1cd
-
-label .control.spdif.space
-
-frame .control.spdif.out
-label .control.spdif.out.text -text "SPDIF Out" -justify left
-checkbutton .control.spdif.out.pro -text "Professional" -anchor nw -width 13 -variable spprof -command setprof -selectcolor blue -font times
-checkbutton .control.spdif.out.emphasis -text "Emphasis" -anchor nw -width 13 -variable spemph -command setemph -selectcolor blue -font times
-checkbutton .control.spdif.out.dolby -text "NoAudio" -anchor nw -width 13 -variable spnoaud -command setnoaud -selectcolor blue -font times
-checkbutton .control.spdif.out.optout -text "Optical Out" -anchor nw -width 13 -variable spoptical -command setoptical -selectcolor blue -font times
-
-pack .control.spdif.out.optout .control.spdif.out.dolby .control.spdif.out.emphasis .control.spdif.out.pro .control.spdif.out.text -side bottom
-
-pack .control.spdif.in .control.spdif.space .control.spdif.out -side top -fill y -padx 3 -expand 1
-
-# Sync Mode & Sync Source
-
-frame .control.sync
-frame .control.sync.mode
-label .control.sync.mode.text -text "Sync Mode" -justify left
-checkbutton .control.sync.mode.master -text "Master" -anchor nw -width 13 -variable master -command setmaster -selectcolor blue -font times
-checkbutton .control.sync.mode.wc -text "Wordclock" -anchor nw -width 13 -variable wordclock -command setwordclock -selectcolor blue -font times
-
-pack .control.sync.mode.text .control.sync.mode.master .control.sync.mode.wc
-
-label .control.sync.space
-
-frame .control.sync.src
-label .control.sync.src.text -text "Sync Source" -justify left
-radiobutton .control.sync.src.input1 -text "ADAT1" -anchor nw -width 13 -variable syncsource -value 1 -command setsyncsource -selectcolor blue -font times
-radiobutton .control.sync.src.input2 -text "ADAT2" -anchor nw -width 13 -variable syncsource -value 2 -command setsyncsource -selectcolor blue -font times
-radiobutton .control.sync.src.input3 -text "ADAT3" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 3 -selectcolor blue -font times
-radiobutton .control.sync.src.input4 -text "SPDIF" -anchor nw -width 13 -variable syncsource -command setsyncsource -value 4 -selectcolor blue -font times
-
-pack .control.sync.src.input4 .control.sync.src.input3 .control.sync.src.input2 .control.sync.src.input1 .control.sync.src.text -side bottom
-
-pack .control.sync.mode .control.sync.space .control.sync.src -side top -fill y -padx 3 -expand 1
-
-label .control.space -text "" -width 10
-
-# Buffer Size
-
-frame .control.buf
-label .control.buf.text -text "Buffer Size (Latency)" -justify left
-radiobutton .control.buf.b1 -selectcolor red -text "64 (1.5 ms)" -width 13 -anchor nw -variable ssrate -value 1 -font times
-radiobutton .control.buf.b2 -selectcolor red -text "128 (3 ms)" -width 13 -anchor nw -variable ssrate -value 2 -font times
-radiobutton .control.buf.b3 -selectcolor red -text "256 (6 ms)" -width 13 -anchor nw -variable ssrate -value 3 -font times
-radiobutton .control.buf.b4 -selectcolor red -text "512 (12 ms)" -width 13 -anchor nw -variable ssrate -value 4 -font times
-radiobutton .control.buf.b5 -selectcolor red -text "1024 (23 ms)" -width 13 -anchor nw -variable ssrate -value 5 -font times
-radiobutton .control.buf.b6 -selectcolor red -text "2048 (46 ms)" -width 13 -anchor nw -variable ssrate -value 6 -font times
-radiobutton .control.buf.b7 -selectcolor red -text "4096 (93 ms)" -width 13 -anchor nw -variable ssrate -value 7 -font times
-radiobutton .control.buf.b8 -selectcolor red -text "8192 (186 ms)" -width 13 -anchor nw -variable ssrate -value 8 -font times
-
-pack .control.buf.text .control.buf.b1 .control.buf.b2 .control.buf.b3 .control.buf.b4 .control.buf.b5 .control.buf.b6 .control.buf.b7 .control.buf.b8 -side top -padx 3 
-
-# Offset
-
-frame .control.offset
-
-frame .control.offset.in
-label .control.offset.in.text -text "Offset In" -justify left
-label .control.offset.in.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
-label .control.offset.in.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
-label .control.offset.in.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
-label .control.offset.in.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
-
-pack .control.offset.in.text .control.offset.in.off0 .control.offset.in.off1 .control.offset.in.off2 .control.offset.in.off3
-
-label .control.offset.space
-
-frame .control.offset.out
-label .control.offset.out.text -text "Offset Out" -justify left
-label .control.offset.out.off0 -text "dev\#0: -" -anchor nw -width 10 -font times
-label .control.offset.out.off1 -text "dev\#1: -" -anchor nw -width 10 -font times
-label .control.offset.out.off2 -text "dev\#2: -" -anchor nw -width 10 -font times
-label .control.offset.out.off3 -text "dev\#3: -" -anchor nw -width 10 -font times
-
-pack .control.offset.out.off3 .control.offset.out.off2 .control.offset.out.off1 .control.offset.out.off0 .control.offset.out.text -side bottom
-
-pack .control.offset.in .control.offset.space .control.offset.out -side top -fill y -padx 3 -expand 1
-
-
-pack .control.spdif .control.sync .control.space .control.buf .control.offset -side left -fill both -anchor n -expand 1
-
-
-label .statustext -text Status -justify center -relief ridge
-label .controltext -text Control -justify center -relief ridge
-
-label .statusspace
-label .controlspace
-
-pack .statustext .status .statusspace .controltext .control .controlspace -side top -anchor nw -fill both -expand 1
-
-
-proc get_bit {output sstr} {
-    set idx1 [string last [concat $sstr 1] $output]
-    set idx1 [expr $idx1 != -1]
-    return $idx1
-}
-
-proc get_val {output sstr} {
-    set val [string wordend $output [string last $sstr $output]] 
-    set val [string range $output $val [expr $val+1]]
-    return $val
-}
-
-proc get_val2 {output sstr} {
-    set val [string wordend $output [string first $sstr $output]] 
-    set val [string range $output $val [expr $val+2]]
-    return $val
-}
-
-proc get_control {} {
-    global spprof
-    global spemph
-    global spnoaud
-    global spoptical
-    global spdifin
-    global ssrate
-    global master
-    global wordclock
-    global syncsource
-    global CTRLPROG
-
-    set f [open "| $CTRLPROG control" r+]
-    set ooo [read $f 1000]
-    close $f
-#    puts $ooo
-
-    set spprof [ get_bit $ooo "pro"]
-    set spemph [ get_bit $ooo "emphasis"]
-    set spnoaud [ get_bit $ooo "dolby"]
-    set spoptical [ get_bit $ooo "opt_out"]
-    set spdifin [ expr [ get_val $ooo "spdif_in"] + 1]
-    set ssrate [ expr [ get_val $ooo "latency"] + 1]
-    set master [ expr [ get_val $ooo "master"]]
-    set wordclock [ expr [ get_val $ooo "wordclock"]]
-    set syncsource [ expr [ get_val $ooo "sync_ref"] + 1]
-}
-
-proc get_status {} {
-    global srate
-    global ctrlcom
-
-    global adatlock1
-    global adatlock2
-    global adatlock3
-
-    global adatsync1
-    global adatsync2
-    global adatsync3
-
-    global tcbusy
-    global tcout
-    global tcvalid
-
-    global spdiferr
-    global crystal
-    global .status.spdif.text
-    global CTRLPROG
-
-
-    set f [open "| $CTRLPROG status" r+]
-    set ooo [read $f 1000]
-    close $f
-#    puts $ooo
-
-# samplerate
-
-    set idx1 [string last "sr48 1" $ooo]
-    set idx2 [string last "doublespeed 1" $ooo]
-    if {$idx1 >= 0} {
-	set fact1 48000
-    } else {
-	set fact1 44100
-    }
-
-    if {$idx2 >= 0} {
-	set fact2 2
-    } else {
-	set fact2 1
-    }
-    set srate [expr $fact1 * $fact2]
-#   ADAT lock
-
-    set val [get_val $ooo lockmask]
-    set adatlock1 0
-    set adatlock2 0
-    set adatlock3 0
-    if {[expr $val & 1]} {
-       set adatlock3 1
-    }
-    if {[expr $val & 2]} {
-       set adatlock2 1
-    }
-    if {[expr $val & 4]} {
-       set adatlock1 1
-    }
-
-#  ADAT sync
-    set val [get_val $ooo syncmask]
-    set adatsync1 0
-    set adatsync2 0
-    set adatsync3 0
-
-    if {[expr $val & 1]} {
-       set adatsync3 1
-    }
-    if {[expr $val & 2]} {
-       set adatsync2 1
-    }
-    if {[expr $val & 4]} {
-       set adatsync1 1
-    }
-
-# TC busy
-
-    set tcbusy [get_bit $ooo "busy"]
-    set tcout [get_bit $ooo "out"]
-    set tcvalid [get_bit $ooo "valid"]
-    set spdiferr [expr [get_bit $ooo "spdif_error"] == 0]
-
-#  000=64kHz, 100=88.2kHz, 011=96kHz
-#  111=32kHz, 110=44.1kHz, 101=48kHz
-
-    set val [get_val $ooo crystalrate]
-
-    set crystal "--.- kHz"
-    if {$val == 0} {
-        set crystal "64 kHz"
-    }
-    if {$val == 4} {
-        set crystal "88.2 kHz"
-    }
-    if {$val == 3} {
-        set crystal "96 kHz"
-    }
-    if {$val == 7} {
-        set crystal "32 kHz"
-    }
-    if {$val == 6} {
-        set crystal "44.1 kHz"
-    }
-    if {$val == 5} {
-        set crystal "48 kHz"
-    }
-    .status.spdif.sr configure -text $crystal
-}
-
-proc get_offset {} {
-    global inoffset
-    global outoffset
-    global CTRLPROG
-
-    set f [open "| $CTRLPROG mix" r+]
-    set ooo [read $f 1000]
-    close $f
-#    puts $ooo
-
-    if { [string match "*devnr*" $ooo] } {
-	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
-	set val [get_val2 $ooo i_offset]
-	.control.offset.in.off0 configure -text "dev\#0: $val"
-	set val [get_val2 $ooo o_offset]
-	.control.offset.out.off0 configure -text "dev\#0: $val"
-    } else {
-	.control.offset.in.off0 configure -text "dev\#0: -"
-	.control.offset.out.off0 configure -text "dev\#0: -"
-    }
-    if { [string match "*devnr*" $ooo] } {
-	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
-	set val [get_val2 $ooo i_offset]
-	.control.offset.in.off1 configure -text "dev\#1: $val"
-	set val [get_val2 $ooo o_offset]
-	.control.offset.out.off1 configure -text "dev\#1: $val"
-    } else {
-	.control.offset.in.off1 configure -text "dev\#1: -"
-	.control.offset.out.off1 configure -text "dev\#1: -"
-    }
-    if { [string match "*devnr*" $ooo] } {
-	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
-	set val [get_val2 $ooo i_offset]
-	.control.offset.in.off2 configure -text "dev\#2: $val"
-	set val [get_val2 $ooo o_offset]
-	.control.offset.out.off2 configure -text "dev\#2: $val"
-    } else {
-	.control.offset.in.off2 configure -text "dev\#2: -"
-	.control.offset.out.off2 configure -text "dev\#2: -"
-    }
-    if { [string match "*devnr*" $ooo] } {
-	set ooo [string range $ooo [string wordend $ooo [string first devnr $ooo]] end]
-	set val [get_val2 $ooo i_offset]
-	.control.offset.in.off3 configure -text "dev\#3: $val"
-	set val [get_val2 $ooo o_offset]
-	.control.offset.out.off3 configure -text "dev\#3: $val"
-    } else {
-	.control.offset.in.off3 configure -text "dev\#3: -"
-	.control.offset.out.off3 configure -text "dev\#3: -"
-    }
-}
-
-
-proc get_all {} {
-get_status
-get_control
-get_offset
-}
-
-# main
-while {1} {
-  after 200
-  get_all
-  update
-}
diff -Nru a/arch/ia64/Kconfig b/arch/ia64/Kconfig
--- a/arch/ia64/Kconfig	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/Kconfig	Sun Feb 29 12:54:28 2004
@@ -288,39 +288,6 @@
 	int
 	default "18"
 
-choice
-	prompt "Huge TLB page size"
-	depends on HUGETLB_PAGE
-	default HUGETLB_PAGE_SIZE_16MB
-
-config HUGETLB_PAGE_SIZE_4GB
-	depends on MCKINLEY
-	bool "4GB"
-
-config HUGETLB_PAGE_SIZE_1GB
-	depends on MCKINLEY
-	bool "1GB"
-
-config HUGETLB_PAGE_SIZE_256MB
-	bool "256MB"
-
-config HUGETLB_PAGE_SIZE_64MB
-	bool "64MB"
-
-config HUGETLB_PAGE_SIZE_16MB
-	bool "16MB"
-
-config HUGETLB_PAGE_SIZE_4MB
-	bool "4MB"
-
-config HUGETLB_PAGE_SIZE_1MB
-	bool "1MB"
-
-config HUGETLB_PAGE_SIZE_256KB
-	bool "256KB"
-
-endchoice
-
 config IA64_PAL_IDLE
 	bool "Use PAL_HALT_LIGHT in idle loop"
 	help
diff -Nru a/arch/ia64/kernel/head.S b/arch/ia64/kernel/head.S
--- a/arch/ia64/kernel/head.S	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/head.S	Sun Feb 29 12:54:28 2004
@@ -816,6 +816,19 @@
 	br.ret.sptk.many rp
 END(ia64_delay_loop)
 
+GLOBAL_ENTRY(ia64_invoke_kernel_thread_helper)
+	.prologue
+	.save rp, r0				// this is the end of the call-chain
+	.body
+	alloc r2 = ar.pfs, 0, 0, 2, 0
+	mov out0 = r9
+	mov out1 = r11;;
+	br.call.sptk.many rp = kernel_thread_helper;;
+	mov out0 = r8
+	br.call.sptk.many rp = sys_exit;;
+1:	br.sptk.few 1b				// not reached
+END(ia64_invoke_kernel_thread_helper)
+
 #ifdef CONFIG_IA64_BRL_EMU
 
 /*
diff -Nru a/arch/ia64/kernel/iosapic.c b/arch/ia64/kernel/iosapic.c
--- a/arch/ia64/kernel/iosapic.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/iosapic.c	Sun Feb 29 12:54:28 2004
@@ -103,6 +103,7 @@
 
 static struct iosapic_intr_info {
 	char		*addr;		/* base address of IOSAPIC */
+	u32		low32;		/* current value of low word of Redirection table entry */
 	unsigned int	gsi_base;	/* first GSI assigned to this IOSAPIC */
 	char		rte_index;	/* IOSAPIC RTE index (-1 => not an IOSAPIC interrupt) */
 	unsigned char	dmode	: 3;	/* delivery mode (see iosapic.h) */
@@ -213,6 +214,7 @@
 	writel(high32, addr + IOSAPIC_WINDOW);
 	writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
 	writel(low32, addr + IOSAPIC_WINDOW);
+	iosapic_intr_info[vector].low32 = low32;
 }
 
 static void
@@ -239,9 +241,10 @@
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
 		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
-		low32 = readl(addr + IOSAPIC_WINDOW);
 
-		low32 |= (1 << IOSAPIC_MASK_SHIFT);    /* set only the mask bit */
+		/* set only the mask bit */
+		low32 = iosapic_intr_info[vec].low32 |= IOSAPIC_MASK;
+
 		writel(low32, addr + IOSAPIC_WINDOW);
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
@@ -264,9 +267,7 @@
 	spin_lock_irqsave(&iosapic_lock, flags);
 	{
 		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
-		low32 = readl(addr + IOSAPIC_WINDOW);
-
-		low32 &= ~(1 << IOSAPIC_MASK_SHIFT);    /* clear only the mask bit */
+		low32 = iosapic_intr_info[vec].low32 &= ~IOSAPIC_MASK;
 		writel(low32, addr + IOSAPIC_WINDOW);
 	}
 	spin_unlock_irqrestore(&iosapic_lock, flags);
@@ -307,9 +308,7 @@
 	{
 		/* get current delivery mode by reading the low32 */
 		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
-		low32 = readl(addr + IOSAPIC_WINDOW);
-
-		low32 &= ~(7 << IOSAPIC_DELIVERY_SHIFT);
+		low32 = iosapic_intr_info[vec].low32 & ~(7 << IOSAPIC_DELIVERY_SHIFT);
 		if (redir)
 		        /* change delivery mode to lowest priority */
 			low32 |= (IOSAPIC_LOWEST_PRIORITY << IOSAPIC_DELIVERY_SHIFT);
@@ -317,6 +316,7 @@
 		        /* change delivery mode to fixed */
 			low32 |= (IOSAPIC_FIXED << IOSAPIC_DELIVERY_SHIFT);
 
+		iosapic_intr_info[vec].low32 = low32;
 		writel(IOSAPIC_RTE_HIGH(rte_index), addr + IOSAPIC_REG_SELECT);
 		writel(high32, addr + IOSAPIC_WINDOW);
 		writel(IOSAPIC_RTE_LOW(rte_index), addr + IOSAPIC_REG_SELECT);
diff -Nru a/arch/ia64/kernel/irq.c b/arch/ia64/kernel/irq.c
--- a/arch/ia64/kernel/irq.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/irq.c	Sun Feb 29 12:54:28 2004
@@ -455,7 +455,6 @@
 	unsigned int status;
 	int cpu;
 
-	irq_enter();
 	cpu = smp_processor_id(); /* for CONFIG_PREEMPT, this must come after irq_enter()! */
 
 	kstat_cpu(cpu).irqs[irq]++;
@@ -525,7 +524,6 @@
 		desc->handler->end(irq);
 		spin_unlock(&desc->lock);
 	}
-	irq_exit();
 	return 1;
 }
 
diff -Nru a/arch/ia64/kernel/irq_ia64.c b/arch/ia64/kernel/irq_ia64.c
--- a/arch/ia64/kernel/irq_ia64.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/irq_ia64.c	Sun Feb 29 12:54:28 2004
@@ -120,6 +120,7 @@
 	 * 16 (without this, it would be ~240, which could easily lead
 	 * to kernel stack overflows).
 	 */
+	irq_enter();
 	saved_tpr = ia64_getreg(_IA64_REG_CR_TPR);
 	ia64_srlz_d();
 	while (vector != IA64_SPURIOUS_INT_VECTOR) {
@@ -143,8 +144,7 @@
 	 * handler needs to be able to wait for further keyboard interrupts, which can't
 	 * come through until ia64_eoi() has been done.
 	 */
-	if (local_softirq_pending())
-		do_softirq();
+	irq_exit();
 }
 
 #ifdef CONFIG_SMP
diff -Nru a/arch/ia64/kernel/ivt.S b/arch/ia64/kernel/ivt.S
--- a/arch/ia64/kernel/ivt.S	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/ivt.S	Sun Feb 29 12:54:28 2004
@@ -118,10 +118,11 @@
 #ifdef CONFIG_HUGETLB_PAGE
 	extr.u r26=r25,2,6
 	;;
-	cmp.eq p8,p0=HPAGE_SHIFT,r26
+	cmp.ne p8,p0=r18,r26
+	sub r27=r26,r18
 	;;
 (p8)	dep r25=r18,r25,2,6
-(p8)	shr r22=r22,HPAGE_SHIFT-PAGE_SHIFT
+(p8)	shr r22=r22,r27
 #endif
 	;;
 	cmp.eq p6,p7=5,r17			// is IFA pointing into to region 5?
diff -Nru a/arch/ia64/kernel/perfmon.c b/arch/ia64/kernel/perfmon.c
--- a/arch/ia64/kernel/perfmon.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/perfmon.c	Sun Feb 29 12:54:28 2004
@@ -82,7 +82,7 @@
 #define PFM_REG_IMPL		0x1 /* register implemented */
 #define PFM_REG_END		0x2 /* end marker */
 #define PFM_REG_MONITOR		(0x1<<4|PFM_REG_IMPL) /* a PMC with a pmc.pm field only */
-#define PFM_REG_COUNTING	(0x2<<4|PFM_REG_MONITOR|PFM_REG_IMPL) /* a monitor + pmc.oi+ PMD used as a counter */
+#define PFM_REG_COUNTING	(0x2<<4|PFM_REG_MONITOR) /* a monitor + pmc.oi+ PMD used as a counter */
 #define PFM_REG_CONTROL		(0x4<<4|PFM_REG_IMPL) /* PMU control register */
 #define	PFM_REG_CONFIG		(0x8<<4|PFM_REG_IMPL) /* configuration register */
 #define PFM_REG_BUFFER	 	(0xc<<4|PFM_REG_IMPL) /* PMD used as buffer */
@@ -109,14 +109,15 @@
 #define PMD_PMD_DEP(i)	   pmu_conf.pmd_desc[i].dep_pmd[0]
 #define PMC_PMD_DEP(i)	   pmu_conf.pmc_desc[i].dep_pmd[0]
 
-/* k assumed unsigned (up to 64 registers) */
-#define IBR_IS_IMPL(k)	  (k< IA64_NUM_DBG_REGS)
-#define DBR_IS_IMPL(k)	  (k< IA64_NUM_DBG_REGS)
+#define PFM_NUM_IBRS	  IA64_NUM_DBG_REGS
+#define PFM_NUM_DBRS	  IA64_NUM_DBG_REGS
 
 #define CTX_OVFL_NOBLOCK(c)	((c)->ctx_fl_block == 0)
 #define CTX_HAS_SMPL(c)		((c)->ctx_fl_is_sampling)
 #define PFM_CTX_TASK(h)		(h)->ctx_task
 
+#define PMU_PMC_OI		5 /* position of pmc.oi bit */
+
 /* XXX: does not support more than 64 PMDs */
 #define CTX_USED_PMD(ctx, mask) (ctx)->ctx_used_pmds[0] |= (mask)
 #define CTX_IS_USED_PMD(ctx, c) (((ctx)->ctx_used_pmds[0] & (1UL << (c))) != 0UL)
@@ -218,6 +219,8 @@
 /*
  * debugging
  */
+#define PFM_DEBUGGING 1
+#ifdef PFM_DEBUGGING
 #define DPRINT(a) \
 	do { \
 		if (unlikely(pfm_sysctl.debug >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \
@@ -227,18 +230,7 @@
 	do { \
 		if (unlikely(pfm_sysctl.debug > 0 && pfm_sysctl.debug_ovfl >0)) { printk("%s.%d: CPU%d [%d] ", __FUNCTION__, __LINE__, smp_processor_id(), current->pid); printk a; } \
 	} while (0)
-/*
- * Architected PMC structure
- */
-typedef struct {
-	unsigned long pmc_plm:4;	/* privilege level mask */
-	unsigned long pmc_ev:1;		/* external visibility */
-	unsigned long pmc_oi:1;		/* overflow interrupt */
-	unsigned long pmc_pm:1;		/* privileged monitor */
-	unsigned long pmc_ig1:1;	/* reserved */
-	unsigned long pmc_es:8;		/* event select */
-	unsigned long pmc_ig2:48;	/* reserved */
-} pfm_monitor_t;
+#endif
 
 /*
  * 64-bit software counter structure
@@ -469,20 +461,13 @@
 #define PFM_CMD_STOP		0x08	/* command does not work on zombie context */
 
 
-#define PFM_CMD_IDX(cmd)	(cmd)
-#define PFM_CMD_IS_VALID(cmd)	((PFM_CMD_IDX(cmd) >= 0) && (PFM_CMD_IDX(cmd) < PFM_CMD_COUNT) \
-				  && pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func != NULL)
-
-#define PFM_CMD_NAME(cmd)	pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_name
-#define PFM_CMD_READ_ARG(cmd)	(pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_READ)
-#define PFM_CMD_RW_ARG(cmd)	(pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_ARG_RW)
-#define PFM_CMD_USE_FD(cmd)	(pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_FD)
-#define PFM_CMD_STOPPED(cmd)	(pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_flags & PFM_CMD_STOP)
+#define PFM_CMD_NAME(cmd)	pfm_cmd_tab[(cmd)].cmd_name
+#define PFM_CMD_READ_ARG(cmd)	(pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_ARG_READ)
+#define PFM_CMD_RW_ARG(cmd)	(pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_ARG_RW)
+#define PFM_CMD_USE_FD(cmd)	(pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_FD)
+#define PFM_CMD_STOPPED(cmd)	(pfm_cmd_tab[(cmd)].cmd_flags & PFM_CMD_STOP)
 
 #define PFM_CMD_ARG_MANY	-1 /* cannot be zero */
-#define PFM_CMD_NARG(cmd)	(pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_narg)
-#define PFM_CMD_ARG_SIZE(cmd)	(pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_argsize)
-#define PFM_CMD_GETSIZE(cmd)	(pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_getsize)
 
 typedef struct {
 	int	debug;		/* turn on/off debugging via syslog */
@@ -2834,10 +2819,11 @@
 pfm_write_pmcs(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
 	struct thread_struct *thread = NULL;
+	struct task_struct *task;
 	pfarg_reg_t *req = (pfarg_reg_t *)arg;
-	unsigned long value;
-	unsigned long smpl_pmds, reset_pmds;
-	unsigned int cnum, reg_flags, flags;
+	unsigned long value, pmc_pm;
+	unsigned long smpl_pmds, reset_pmds, impl_pmds;
+	unsigned int cnum, reg_flags, flags, pmc_type;
 	int i, can_access_pmu = 0, is_loaded, is_system;
 	int is_monitor, is_counting, state;
 	int ret = -EINVAL;
@@ -2846,12 +2832,13 @@
 	state     = ctx->ctx_state;
 	is_loaded = state == PFM_CTX_LOADED ? 1 : 0;
 	is_system = ctx->ctx_fl_system;
+	task      = ctx->ctx_task;
+	impl_pmds = pmu_conf.impl_pmds[0];
 
 	if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL;
 
-
 	if (is_loaded) {
-		thread = &ctx->ctx_task->thread;
+		thread = &task->thread;
 		/*
 		 * In system wide and when the context is loaded, access can only happen
 		 * when the caller is running on the CPU being monitored by the session.
@@ -2861,7 +2848,7 @@
 			DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
 			return -EBUSY;
 		}
-		can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0;
+		can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0;
 	}
 
 	for (i = 0; i < count; i++, req++) {
@@ -2873,16 +2860,24 @@
 		reset_pmds = req->reg_reset_pmds[0];
 		flags      = 0;
 
-		is_counting = PMC_IS_COUNTING(cnum);
-		is_monitor  = PMC_IS_MONITOR(cnum);
+
+		if (cnum >= PMU_MAX_PMCS) {
+			DPRINT(("pmc%u is invalid\n", cnum));
+			goto error;
+		}
+
+		pmc_type   = pmu_conf.pmc_desc[cnum].type;
+		pmc_pm     = (value >> pmu_conf.pmc_desc[cnum].pm_pos) & 0x1;
+		is_counting = (pmc_type & PFM_REG_COUNTING) == PFM_REG_COUNTING ? 1 : 0;
+		is_monitor  = (pmc_type & PFM_REG_MONITOR) == PFM_REG_MONITOR ? 1 : 0;
 
 		/*
 		 * we reject all non implemented PMC as well
 		 * as attempts to modify PMC[0-3] which are used
 		 * as status registers by the PMU
 		 */
-		if (PMC_IS_IMPL(cnum) == 0 || PMC_IS_CONTROL(cnum)) {
-			DPRINT(("pmc%u is unimplemented or invalid\n", cnum));
+		if ((pmc_type & PFM_REG_IMPL) == 0 || (pmc_type & PFM_REG_CONTROL) == PFM_REG_CONTROL) {
+			DPRINT(("pmc%u is unimplemented or no-access pmc_type=%x\n", cnum, pmc_type));
 			goto error;
 		}
 		/*
@@ -2890,21 +2885,20 @@
 		 * 	- system-wide session: PMCx.pm=1 (privileged monitor)
 		 * 	- per-task           : PMCx.pm=0 (user monitor)
 		 */
-		if ((is_monitor || is_counting) && value != PMC_DFL_VAL(cnum) && PFM_CHECK_PMC_PM(ctx, cnum, value)) {
-			DPRINT(("pmc%u pmc_pm=%ld fl_system=%d\n",
+		if (is_monitor && value != PMC_DFL_VAL(cnum) && is_system ^ pmc_pm) {
+			DPRINT(("pmc%u pmc_pm=%lu is_system=%d\n",
 				cnum,
-				PMC_PM(cnum, value),
-				ctx->ctx_fl_system));
+				pmc_pm,
+				is_system));
 			goto error;
 		}
 
 		if (is_counting) {
-			pfm_monitor_t *p = (pfm_monitor_t *)&value;
 			/*
 		 	 * enforce generation of overflow interrupt. Necessary on all
 		 	 * CPUs.
 		 	 */
-			p->pmc_oi = 1;
+			value |= 1 << PMU_PMC_OI;
 
 			if (reg_flags & PFM_REGFL_OVFL_NOTIFY) {
 				flags |= PFM_REGFL_OVFL_NOTIFY;
@@ -2913,13 +2907,13 @@
 			if (reg_flags & PFM_REGFL_RANDOM) flags |= PFM_REGFL_RANDOM;
 
 			/* verify validity of smpl_pmds */
-			if ((smpl_pmds & pmu_conf.impl_pmds[0]) != smpl_pmds) {
+			if ((smpl_pmds & impl_pmds) != smpl_pmds) {
 				DPRINT(("invalid smpl_pmds 0x%lx for pmc%u\n", smpl_pmds, cnum));
 				goto error;
 			}
 
 			/* verify validity of reset_pmds */
-			if ((reset_pmds & pmu_conf.impl_pmds[0]) != reset_pmds) {
+			if ((reset_pmds & impl_pmds) != reset_pmds) {
 				DPRINT(("invalid reset_pmds 0x%lx for pmc%u\n", reset_pmds, cnum));
 				goto error;
 			}
@@ -2935,7 +2929,7 @@
 		 * execute write checker, if any
 		 */
 		if (PMC_WR_FUNC(cnum)) {
-			ret = PMC_WR_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &value, regs);
+			ret = PMC_WR_FUNC(cnum)(task, ctx, cnum, &value, regs);
 			if (ret) goto error;
 			ret = -EINVAL;
 		}
@@ -2997,7 +2991,7 @@
 		 *
 		 * The value in ctx_pmcs[] can only be changed in pfm_write_pmcs().
 		 *
-		 * The value in t->pmc[] may be modified on overflow, i.e.,  when
+		 * The value in thread->pmcs[] may be modified on overflow, i.e.,  when
 		 * monitoring needs to be stopped.
 		 */
 		if (is_monitor) CTX_USED_MONITOR(ctx, 1UL << cnum);
@@ -3056,11 +3050,6 @@
 	return 0;
 error:
 	PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL);
-
-	req->reg_flags = PFM_REG_RETFL_EINVAL;
-
-	DPRINT(("pmc[%u]=0x%lx error %d\n", cnum, value, ret));
-
 	return ret;
 }
 
@@ -3068,6 +3057,7 @@
 pfm_write_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
 	struct thread_struct *thread = NULL;
+	struct task_struct *task;
 	pfarg_reg_t *req = (pfarg_reg_t *)arg;
 	unsigned long value, hw_value, ovfl_mask;
 	unsigned int cnum;
@@ -3080,25 +3070,26 @@
 	is_loaded = state == PFM_CTX_LOADED ? 1 : 0;
 	is_system = ctx->ctx_fl_system;
 	ovfl_mask = pmu_conf.ovfl_val;
+	task      = ctx->ctx_task;
 
-	if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL;
+	if (unlikely(state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE)) return -EINVAL;
 
 	/*
 	 * on both UP and SMP, we can only write to the PMC when the task is
 	 * the owner of the local PMU.
 	 */
-	if (is_loaded) {
-		thread = &ctx->ctx_task->thread;
+	if (likely(is_loaded)) {
+		thread = &task->thread;
 		/*
 		 * In system wide and when the context is loaded, access can only happen
 		 * when the caller is running on the CPU being monitored by the session.
 		 * It does not have to be the owner (ctx_task) of the context per se.
 		 */
-		if (is_system && ctx->ctx_cpu != smp_processor_id()) {
+		if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) {
 			DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
 			return -EBUSY;
 		}
-		can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0;
+		can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0;
 	}
 
 	for (i = 0; i < count; i++, req++) {
@@ -3118,7 +3109,7 @@
 		if (PMD_WR_FUNC(cnum)) {
 			unsigned long v = value;
 
-			ret = PMD_WR_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &v, regs);
+			ret = PMD_WR_FUNC(cnum)(task, ctx, cnum, &v, regs);
 			if (ret) goto abort_mission;
 
 			value = v;
@@ -3243,16 +3234,6 @@
 	 * for now, we have only one possibility for error
 	 */
 	PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL);
-
-	/*
-	 * we change the return value to EFAULT in case we cannot write register return code.
-	 * The caller first must correct this error, then a resubmission of the request will
-	 * eventually yield the EINVAL.
-	 */
-	req->reg_flags = PFM_REG_RETFL_EINVAL;
-
-	DPRINT(("pmd[%u]=0x%lx ret %d\n", cnum, value, ret));
-
 	return ret;
 }
 
@@ -3269,11 +3250,12 @@
 pfm_read_pmds(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
 	struct thread_struct *thread = NULL;
-	unsigned long val = 0UL, lval, ovfl_mask;
+	struct task_struct *task;
+	unsigned long val = 0UL, lval, ovfl_mask, sval;
 	pfarg_reg_t *req = (pfarg_reg_t *)arg;
 	unsigned int cnum, reg_flags = 0;
 	int i, can_access_pmu = 0, state;
-	int is_loaded, is_system;
+	int is_loaded, is_system, is_counting;
 	int ret = -EINVAL;
 
 	/*
@@ -3285,32 +3267,33 @@
 	is_loaded = state == PFM_CTX_LOADED ? 1 : 0;
 	is_system = ctx->ctx_fl_system;
 	ovfl_mask = pmu_conf.ovfl_val;
+	task      = ctx->ctx_task;
 
 	if (state == PFM_CTX_ZOMBIE) return -EINVAL;
 
-	if (is_loaded) {
-		thread = &ctx->ctx_task->thread;
+	if (likely(is_loaded)) {
+		thread = &task->thread;
 		/*
 		 * In system wide and when the context is loaded, access can only happen
 		 * when the caller is running on the CPU being monitored by the session.
 		 * It does not have to be the owner (ctx_task) of the context per se.
 		 */
-		if (is_system && ctx->ctx_cpu != smp_processor_id()) {
+		if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) {
 			DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
 			return -EBUSY;
 		}
 		/*
 		 * this can be true when not self-monitoring only in UP
 		 */
-		can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0;
+		can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0;
 
 		if (can_access_pmu) ia64_srlz_d();
 	}
 
-	DPRINT(("enter loaded=%d access_pmu=%d ctx_state=%d\n",
+	DPRINT(("loaded=%d access_pmu=%d ctx_state=%d\n",
 		is_loaded,
 		can_access_pmu,
-		ctx->ctx_state));
+		state));
 
 	/*
 	 * on both UP and SMP, we can only read the PMD from the hardware register when
@@ -3319,11 +3302,10 @@
 
 	for (i = 0; i < count; i++, req++) {
 
-		lval        = 0UL;
 		cnum        = req->reg_num;
 		reg_flags   = req->reg_flags;
 
-		if (!PMD_IS_IMPL(cnum)) goto error;
+		if (unlikely(!PMD_IS_IMPL(cnum))) goto error;
 		/*
 		 * we can only read the register that we use. That includes
 		 * the one we explicitely initialize AND the one we want included
@@ -3332,7 +3314,11 @@
 		 * Having this restriction allows optimization in the ctxsw routine
 		 * without compromising security (leaks)
 		 */
-		if (!CTX_IS_USED_PMD(ctx, cnum)) goto error;
+		if (unlikely(!CTX_IS_USED_PMD(ctx, cnum))) goto error;
+
+		sval        = ctx->ctx_pmds[cnum].val;
+		lval        = ctx->ctx_pmds[cnum].lval;
+		is_counting = PMD_IS_COUNTING(cnum);
 
 		/*
 		 * If the task is not the current one, then we check if the
@@ -3347,23 +3333,21 @@
 			 * if context is zombie, then task does not exist anymore.
 			 * In this case, we use the full value saved in the context (pfm_flush_regs()).
 			 */
-			val = state == PFM_CTX_LOADED ? thread->pmds[cnum] : 0UL;
+			val = is_loaded ? thread->pmds[cnum] : 0UL;
 		}
 
-		if (PMD_IS_COUNTING(cnum)) {
+		if (is_counting) {
 			/*
 			 * XXX: need to check for overflow when loaded
 			 */
 			val &= ovfl_mask;
-			val += ctx->ctx_pmds[cnum].val;
-
-			lval = ctx->ctx_pmds[cnum].lval;
+			val += sval;
 		}
 
 		/*
 		 * execute read checker, if any
 		 */
-		if (PMD_RD_FUNC(cnum)) {
+		if (unlikely(PMD_RD_FUNC(cnum))) {
 			unsigned long v = val;
 			ret = PMD_RD_FUNC(cnum)(ctx->ctx_task, ctx, cnum, &v, regs);
 			if (ret) goto error;
@@ -3373,12 +3357,7 @@
 
 		PFM_REG_RETFLAG_SET(reg_flags, 0);
 
-		DPRINT(("pmd[%u]=0x%lx loaded=%d access_pmu=%d ctx_state=%d\n",
-			cnum,
-			val,
-			is_loaded,
-			can_access_pmu,
-			ctx->ctx_state));
+		DPRINT(("pmd[%u]=0x%lx\n", cnum, val));
 
 		/*
 		 * update register return value, abort all if problem during copy.
@@ -3393,12 +3372,7 @@
 	return 0;
 
 error:
-	PFM_REG_RETFLAG_SET(reg_flags, PFM_REG_RETFL_EINVAL);
-
-	req->reg_flags = PFM_REG_RETFL_EINVAL;
-
-	DPRINT(("error pmd[%u]=0x%lx\n", cnum, val));
-
+	PFM_REG_RETFLAG_SET(req->reg_flags, PFM_REG_RETFL_EINVAL);
 	return ret;
 }
 
@@ -3628,7 +3602,7 @@
 			prefetch(ctx->ctx_smpl_hdr);
 
 			rst_ctrl.bits.mask_monitoring = 0;
-			rst_ctrl.bits.reset_ovfl_pmds = 1;
+			rst_ctrl.bits.reset_ovfl_pmds = 0;
 
 			if (state == PFM_CTX_LOADED)
 				ret = pfm_buf_fmt_restart_active(fmt, task, &rst_ctrl, ctx->ctx_smpl_hdr, regs);
@@ -3748,6 +3722,7 @@
 pfm_write_ibr_dbr(int mode, pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs)
 {
 	struct thread_struct *thread = NULL;
+	struct task_struct *task;
 	pfarg_dbreg_t *req = (pfarg_dbreg_t *)arg;
 	unsigned long flags;
 	dbreg_t dbreg;
@@ -3762,6 +3737,7 @@
 	state     = ctx->ctx_state;
 	is_loaded = state == PFM_CTX_LOADED ? 1 : 0;
 	is_system = ctx->ctx_fl_system;
+	task      = ctx->ctx_task;
 
 	if (state == PFM_CTX_TERMINATED || state == PFM_CTX_ZOMBIE) return -EINVAL;
 
@@ -3770,17 +3746,17 @@
 	 * the owner of the local PMU.
 	 */
 	if (is_loaded) {
-		thread = &ctx->ctx_task->thread;
+		thread = &task->thread;
 		/*
 		 * In system wide and when the context is loaded, access can only happen
 		 * when the caller is running on the CPU being monitored by the session.
 		 * It does not have to be the owner (ctx_task) of the context per se.
 		 */
-		if (is_system && ctx->ctx_cpu != smp_processor_id()) {
+		if (unlikely(is_system && ctx->ctx_cpu != smp_processor_id())) {
 			DPRINT(("[%d] should be running on CPU%d\n", current->pid, ctx->ctx_cpu));
 			return -EBUSY;
 		}
-		can_access_pmu = GET_PMU_OWNER() == ctx->ctx_task || is_system ? 1 : 0;
+		can_access_pmu = GET_PMU_OWNER() == task || is_system ? 1 : 0;
 	}
 
 	/*
@@ -3796,7 +3772,7 @@
 	 * don't bother if we are loaded and task is being debugged
 	 */
 	if (is_loaded && (thread->flags & IA64_THREAD_DBG_VALID) != 0) {
-		DPRINT(("debug registers already in use for [%d]\n", ctx->ctx_task->pid));
+		DPRINT(("debug registers already in use for [%d]\n", task->pid));
 		return -EBUSY;
 	}
 
@@ -3837,7 +3813,7 @@
 	 * is shared by all processes running on it
  	 */
 	if (first_time && can_access_pmu) {
-		DPRINT(("[%d] clearing ibrs, dbrs\n", ctx->ctx_task->pid));
+		DPRINT(("[%d] clearing ibrs, dbrs\n", task->pid));
 		for (i=0; i < pmu_conf.num_ibrs; i++) {
 			ia64_set_ibr(i, 0UL);
 			ia64_srlz_i();
@@ -3860,7 +3836,7 @@
 
 		ret = -EINVAL;
 
-		if ((mode == PFM_CODE_RR && !IBR_IS_IMPL(rnum)) || ((mode == PFM_DATA_RR) && !DBR_IS_IMPL(rnum))) {
+		if ((mode == PFM_CODE_RR && rnum >= PFM_NUM_IBRS) || ((mode == PFM_DATA_RR) && rnum >= PFM_NUM_DBRS)) {
 			DPRINT(("invalid register %u val=0x%lx mode=%d i=%d count=%d\n",
 				  rnum, dbreg.val, mode, i, count));
 
@@ -4434,6 +4410,7 @@
 	struct task_struct *task = PFM_CTX_TASK(ctx);
 	struct pt_regs *tregs;
 	int state, is_system;
+	int ret;
 
 	DPRINT(("ctx_state=%d task [%d]\n", ctx->ctx_state, task ? task->pid : -1));
 
@@ -4451,7 +4428,8 @@
 	/*
 	 * clear psr and dcr bits
 	 */
-	pfm_stop(ctx, NULL, 0, regs);
+	ret = pfm_stop(ctx, NULL, 0, regs);
+	if (ret) return ret;
 
 	ctx->ctx_state = state = PFM_CTX_UNLOADED;
 
@@ -4760,37 +4738,45 @@
 	void *args_k = NULL;
 	long ret; /* will expand int return types */
 	size_t base_sz, sz, xtra_sz = 0;
-	int narg, completed_args = 0, call_made = 0;
+	int narg, completed_args = 0, call_made = 0, cmd_flags;
+	int (*func)(pfm_context_t *ctx, void *arg, int count, struct pt_regs *regs);
+	int (*getsize)(void *arg, size_t *sz);
 #define PFM_MAX_ARGSIZE	4096
 
 	/*
-	 * reject any call if perfmon was disabled at initialization time
-	 mask*/
-	if (PFM_IS_DISABLED()) return -ENOSYS;
+	 * reject any call if perfmon was disabled at initialization
+	 */
+	if (unlikely(PFM_IS_DISABLED())) return -ENOSYS;
+
+	if (unlikely(cmd < 0 || cmd >= PFM_CMD_COUNT)) {
+		DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd));
+		return -EINVAL;
+	}
+
+	func      = pfm_cmd_tab[cmd].cmd_func;
+	narg      = pfm_cmd_tab[cmd].cmd_narg;
+	base_sz   = pfm_cmd_tab[cmd].cmd_argsize;
+	getsize   = pfm_cmd_tab[cmd].cmd_getsize;
+	cmd_flags = pfm_cmd_tab[cmd].cmd_flags;
 
-	if (unlikely(PFM_CMD_IS_VALID(cmd) == 0)) {
+	if (unlikely(func == NULL)) {
 		DPRINT(("[%d] invalid cmd=%d\n", current->pid, cmd));
 		return -EINVAL;
 	}
 
-	DPRINT(("cmd=%s idx=%d valid=%d narg=0x%x argsz=%lu count=%d\n",
+	DPRINT(("cmd=%s idx=%d narg=0x%x argsz=%lu count=%d\n",
 		PFM_CMD_NAME(cmd),
-		PFM_CMD_IDX(cmd),
-		PFM_CMD_IS_VALID(cmd),
-		PFM_CMD_NARG(cmd),
-		PFM_CMD_ARG_SIZE(cmd), 
+		cmd,
+		narg,
+		base_sz,
 		count));
 
 	/*
 	 * check if number of arguments matches what the command expects
 	 */
-	narg = PFM_CMD_NARG(cmd);
-	if ((narg == PFM_CMD_ARG_MANY && count <= 0) || (narg > 0 && narg != count))
+	if (unlikely((narg == PFM_CMD_ARG_MANY && count <= 0) || (narg > 0 && narg != count)))
 		return -EINVAL;
 
-	/* get single argument size */
-	base_sz = PFM_CMD_ARG_SIZE(cmd);
-
 restart_args:
 	sz = xtra_sz + base_sz*count;
 	/*
@@ -4804,7 +4790,7 @@
 	/*
 	 * allocate default-sized argument buffer
 	 */
-	if (count && args_k == NULL) {
+	if (likely(count && args_k == NULL)) {
 		args_k = kmalloc(PFM_MAX_ARGSIZE, GFP_KERNEL);
 		if (args_k == NULL) return -ENOMEM;
 	}
@@ -4824,11 +4810,11 @@
 	/*
 	 * check if command supports extra parameters
 	 */
-	if (completed_args == 0 && PFM_CMD_GETSIZE(cmd)) {
+	if (completed_args == 0 && getsize) {
 		/*
 		 * get extra parameters size (based on main argument)
 		 */
-		ret = PFM_CMD_GETSIZE(cmd)(args_k, &xtra_sz);
+		ret = (*getsize)(args_k, &xtra_sz);
 		if (ret) goto error_args;
 
 		completed_args = 1;
@@ -4836,45 +4822,45 @@
 		DPRINT(("[%d] restart_args sz=%lu xtra_sz=%lu\n", current->pid, sz, xtra_sz));
 
 		/* retry if necessary */
-		if (xtra_sz) goto restart_args;
+		if (likely(xtra_sz)) goto restart_args;
 	}
 
-	if (PFM_CMD_USE_FD(cmd))  {
+	if (unlikely((cmd_flags & PFM_CMD_FD) == 0)) goto skip_fd;
 
-		ret = -EBADF;
-
-		file = fget(fd);
-		if (file == NULL) {
-			DPRINT(("[%d] invalid fd %d\n", current->pid, fd));
-			goto error_args;
-		}
-		if (PFM_IS_FILE(file) == 0) {
-			DPRINT(("[%d] fd %d not related to perfmon\n", current->pid, fd));
-			goto error_args;
-		}
+	ret = -EBADF;
 
+	file = fget(fd);
+	if (unlikely(file == NULL)) {
+		DPRINT(("[%d] invalid fd %d\n", current->pid, fd));
+		goto error_args;
+	}
+	if (unlikely(PFM_IS_FILE(file) == 0)) {
+		DPRINT(("[%d] fd %d not related to perfmon\n", current->pid, fd));
+		goto error_args;
+	}
 
-		ctx = (pfm_context_t *)file->private_data;
-		if (ctx == NULL) {
-			DPRINT(("[%d] no context for fd %d\n", current->pid, fd));
-			goto error_args;
-		}
+	ctx = (pfm_context_t *)file->private_data;
+	if (unlikely(ctx == NULL)) {
+		DPRINT(("[%d] no context for fd %d\n", current->pid, fd));
+		goto error_args;
+	}
+	prefetch(&ctx->ctx_state);
 
-		PROTECT_CTX(ctx, flags);
+	PROTECT_CTX(ctx, flags);
 
-		/*
-		 * check task is stopped
-		 */
-		ret = pfm_check_task_state(ctx, cmd, flags);
-		if (ret) goto abort_locked;
-	}
+	/*
+	 * check task is stopped
+	 */
+	ret = pfm_check_task_state(ctx, cmd, flags);
+	if (unlikely(ret)) goto abort_locked;
 
-	ret = (*pfm_cmd_tab[PFM_CMD_IDX(cmd)].cmd_func)(ctx, args_k, count, regs);
+skip_fd:
+	ret = (*func)(ctx, args_k, count, regs);
 
 	call_made = 1;
 
 abort_locked:
-	if (ctx) {
+	if (likely(ctx)) {
 		DPRINT(("[%d] context unlocked\n", current->pid));
 		UNPROTECT_CTX(ctx, flags);
 		fput(file);
@@ -4907,7 +4893,7 @@
 	if (CTX_HAS_SMPL(ctx)) {
 
 		rst_ctrl.bits.mask_monitoring = 0;
-		rst_ctrl.bits.reset_ovfl_pmds = 1;
+		rst_ctrl.bits.reset_ovfl_pmds = 0;
 
 		if (state == PFM_CTX_LOADED)
 			ret = pfm_buf_fmt_restart_active(fmt, current, &rst_ctrl, ctx->ctx_smpl_hdr, regs);
@@ -5096,7 +5082,7 @@
 		msg->pfm_ovfl_msg.msg_ovfl_pmds[1] = 0UL;
 		msg->pfm_ovfl_msg.msg_ovfl_pmds[2] = 0UL;
 		msg->pfm_ovfl_msg.msg_ovfl_pmds[3] = 0UL;
-		msg->pfm_ovfl_msg.msg_tstamp       = ia64_get_itc(); /* relevant on UP only */
+		msg->pfm_ovfl_msg.msg_tstamp       = 0UL;
 	}
 
 	DPRINT(("ovfl msg: msg=%p no_msg=%d fd=%d pid=%d ovfl_pmds=0x%lx\n",
@@ -5119,10 +5105,12 @@
 		printk(KERN_ERR "perfmon: pfm_end_notify_user no more notification msgs\n");
 		return -1;
 	}
+	/* no leak */
+	memset(msg, 0, sizeof(*msg));
 
 	msg->pfm_end_msg.msg_type    = PFM_MSG_END;
 	msg->pfm_end_msg.msg_ctx_fd  = ctx->ctx_fd;
-	msg->pfm_ovfl_msg.msg_tstamp = ia64_get_itc(); /* relevant on UP only */
+	msg->pfm_ovfl_msg.msg_tstamp = 0UL;
 
 	DPRINT(("end msg: msg=%p no_msg=%d ctx_fd=%d pid=%d\n",
 		msg,
@@ -5141,8 +5129,8 @@
 {
 	pfm_ovfl_arg_t ovfl_arg;
 	unsigned long mask;
-	unsigned long old_val, ovfl_val;
-	unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL;
+	unsigned long old_val, ovfl_val, new_val;
+	unsigned long ovfl_notify = 0UL, ovfl_pmds = 0UL, smpl_pmds = 0UL, reset_pmds;
 	unsigned long tstamp;
 	pfm_ovfl_ctrl_t	ovfl_ctrl;
 	unsigned int i, has_smpl;
@@ -5155,21 +5143,19 @@
 	 */
 	if (unlikely((pmc0 & 0x1) == 0)) goto sanity_check;
 
-	tstamp = ia64_get_itc();
-
+	tstamp   = ia64_get_itc();
 	mask     = pmc0 >> PMU_FIRST_COUNTER;
 	ovfl_val = pmu_conf.ovfl_val;
+	has_smpl = CTX_HAS_SMPL(ctx);
 
 	DPRINT_ovfl(("pmc0=0x%lx pid=%d iip=0x%lx, %s "
-		     "used_pmds=0x%lx reload_pmcs=0x%lx\n",
+		     "used_pmds=0x%lx\n",
 			pmc0,
 			task ? task->pid: -1,
 			(regs ? regs->cr_iip : 0),
 			CTX_OVFL_NOBLOCK(ctx) ? "nonblocking" : "blocking",
-			ctx->ctx_used_pmds[0],
-			ctx->ctx_reload_pmcs[0]));
+			ctx->ctx_used_pmds[0]));
 
-	has_smpl = CTX_HAS_SMPL(ctx);
 
 	/*
 	 * first we update the virtual counters
@@ -5180,29 +5166,31 @@
 		/* skip pmd which did not overflow */
 		if ((mask & 0x1) == 0) continue;
 
-		DPRINT_ovfl(("pmd[%d] overflowed hw_pmd=0x%lx ctx_pmd=0x%lx\n",
-			i, ia64_get_pmd(i), ctx->ctx_pmds[i].val));
-
 		/*
 		 * Note that the pmd is not necessarily 0 at this point as qualified events
 		 * may have happened before the PMU was frozen. The residual count is not
 		 * taken into consideration here but will be with any read of the pmd via
 		 * pfm_read_pmds().
 		 */
-		old_val               = ctx->ctx_pmds[i].val;
-		ctx->ctx_pmds[i].val += 1 + ovfl_val;
+		old_val              = new_val = ctx->ctx_pmds[i].val;
+		new_val             += 1 + ovfl_val;
+		ctx->ctx_pmds[i].val = new_val;
 
 		/*
 		 * check for overflow condition
 		 */
-		if (likely(old_val > ctx->ctx_pmds[i].val)) {
+		if (likely(old_val > new_val)) {
 			ovfl_pmds |= 1UL << i;
 			if (PMC_OVFL_NOTIFY(ctx, i)) ovfl_notify |= 1UL << i;
 		}
 
-		DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx smpl_pmds=0x%lx\n",
-			i, ctx->ctx_pmds[i].val, old_val,
-			ia64_get_pmd(i) & ovfl_val, ovfl_pmds, ovfl_notify, smpl_pmds));
+		DPRINT_ovfl(("ctx_pmd[%d].val=0x%lx old_val=0x%lx pmd=0x%lx ovfl_pmds=0x%lx ovfl_notify=0x%lx\n",
+			i,
+			new_val,
+			old_val,
+			ia64_get_pmd(i) & ovfl_val,
+			ovfl_pmds,
+			ovfl_notify));
 	}
 
 	/*
@@ -5214,6 +5202,7 @@
 	 * reset all control bits
 	 */
 	ovfl_ctrl.val = 0;
+	reset_pmds    = 0UL;
 
 	/*
 	 * if a sampling format module exists, then we "cache" the overflow by 
@@ -5225,7 +5214,7 @@
 		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;
 
 		prefetch(ctx->ctx_smpl_hdr);
 
@@ -5275,7 +5264,10 @@
 			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.reset_ovfl_pmds |= ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds; /* yes or no */
+			/*
+			 * build the bitmask of pmds to reset now
+			 */
+			if (ovfl_arg.ovfl_ctrl.bits.reset_ovfl_pmds) reset_pmds |= mask;
 
 			pfm_stats[this_cpu].pfm_smpl_handler_cycles += end_cycles - start_cycles;
 		}
@@ -5287,6 +5279,10 @@
 				current->pid,
 				pmd_mask<<PMU_FIRST_COUNTER));
 		}
+		/*
+		 * remove the pmds we reset now from the set of pmds to reset in pfm_restart()
+		 */
+		ovfl_pmds &= ~reset_pmds;
 	} else {
 		/*
 		 * when no sampling module is used, then the default
@@ -5296,14 +5292,21 @@
 		ovfl_ctrl.bits.block_task      = ovfl_notify ? 1 : 0;
 		ovfl_ctrl.bits.mask_monitoring = ovfl_notify ? 1 : 0; /* XXX: change for saturation */
 		ovfl_ctrl.bits.reset_ovfl_pmds = ovfl_notify ? 0 : 1;
+		/*
+		 * if needed, we reset all overflowed pmds
+		 */
+		if (ovfl_notify == 0) reset_pmds = ovfl_pmds;
 	}
 
+	DPRINT(("current [%d] ovfl_pmds=0x%lx reset_pmds=0x%lx\n",
+		current->pid,
+		ovfl_pmds,
+		reset_pmds));
 	/*
-	 * if we (still) have some overflowed PMD but no notification is requested
-	 * then we use the short reset period.
+	 * reset the requested PMD registers using the short reset values
 	 */
-	if (ovfl_ctrl.bits.reset_ovfl_pmds) {
-		unsigned long bm = ovfl_pmds;
+	if (reset_pmds) {
+		unsigned long bm = reset_pmds;
 		pfm_reset_regs(ctx, &bm, PFM_PMD_SHORT_RESET);
 	}
 
diff -Nru a/arch/ia64/kernel/perfmon_default_smpl.c b/arch/ia64/kernel/perfmon_default_smpl.c
--- a/arch/ia64/kernel/perfmon_default_smpl.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/perfmon_default_smpl.c	Sun Feb 29 12:54:28 2004
@@ -178,6 +178,7 @@
 	ent->tstamp    = stamp;
 	ent->cpu       = smp_processor_id();
 	ent->set       = arg->active_set;
+	ent->tgid      = current->tgid;
 
 	/*
 	 * selectively store PMDs in increasing index number
diff -Nru a/arch/ia64/kernel/process.c b/arch/ia64/kernel/process.c
--- a/arch/ia64/kernel/process.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/kernel/process.c	Sun Feb 29 12:54:28 2004
@@ -259,10 +259,12 @@
  *
  * We get here through the following  call chain:
  *
- *	<clone syscall>
- *	sys_clone
- *	do_fork
- *	copy_thread
+ *	from user-level:	from kernel:
+ *
+ *	<clone syscall>	        <some kernel call frames>
+ *	sys_clone		   :
+ *	do_fork			do_fork
+ *	copy_thread		copy_thread
  *
  * This means that the stack layout is as follows:
  *
@@ -276,9 +278,6 @@
  *	|                     | <-- sp (lowest addr)
  *	+---------------------+
  *
- * Note: if we get called through kernel_thread() then the memory above "(highest addr)"
- * is valid kernel stack memory that needs to be copied as well.
- *
  * Observe that we copy the unat values that are in pt_regs and switch_stack.  Spilling an
  * integer to address X causes bit N in ar.unat to be set to the NaT bit of the register,
  * with N=(X & 0x1ff)/8.  Thus, copying the unat value preserves the NaT bits ONLY if the
@@ -291,9 +290,9 @@
 	     unsigned long user_stack_base, unsigned long user_stack_size,
 	     struct task_struct *p, struct pt_regs *regs)
 {
-	unsigned long rbs, child_rbs, rbs_size, stack_offset, stack_top, stack_used;
-	struct switch_stack *child_stack, *stack;
 	extern char ia64_ret_from_clone, ia32_ret_from_clone;
+	struct switch_stack *child_stack, *stack;
+	unsigned long rbs, child_rbs, rbs_size;
 	struct pt_regs *child_ptregs;
 	int retval = 0;
 
@@ -306,16 +305,13 @@
 		return 0;
 #endif
 
-	stack_top = (unsigned long) current + IA64_STK_OFFSET;
 	stack = ((struct switch_stack *) regs) - 1;
-	stack_used = stack_top - (unsigned long) stack;
-	stack_offset = IA64_STK_OFFSET - stack_used;
 
-	child_stack = (struct switch_stack *) ((unsigned long) p + stack_offset);
-	child_ptregs = (struct pt_regs *) (child_stack + 1);
+	child_ptregs = (struct pt_regs *) ((unsigned long) p + IA64_STK_OFFSET) - 1;
+	child_stack = (struct switch_stack *) child_ptregs - 1;
 
 	/* copy parent's switch_stack & pt_regs to child: */
-	memcpy(child_stack, stack, stack_used);
+	memcpy(child_stack, stack, sizeof(*child_ptregs) + sizeof(*child_stack));
 
 	rbs = (unsigned long) current + IA64_RBS_OFFSET;
 	child_rbs = (unsigned long) p + IA64_RBS_OFFSET;
@@ -324,7 +320,7 @@
 	/* copy the parent's register backing store to the child: */
 	memcpy((void *) child_rbs, (void *) rbs, rbs_size);
 
-	if (user_mode(child_ptregs)) {
+	if (likely(user_mode(child_ptregs))) {
 		if ((clone_flags & CLONE_SETTLS) && !IS_IA32_PROCESS(regs))
 			child_ptregs->r13 = regs->r16;	/* see sys_clone2() in entry.S */
 		if (user_stack_base) {
@@ -341,14 +337,14 @@
 		 * been taken care of by the caller of sys_clone()
 		 * already.
 		 */
-		child_ptregs->r12 = (unsigned long) (child_ptregs + 1); /* kernel sp */
+		child_ptregs->r12 = (unsigned long) child_ptregs - 16; /* kernel sp */
 		child_ptregs->r13 = (unsigned long) p;		/* set `current' pointer */
 	}
+	child_stack->ar_bspstore = child_rbs + rbs_size;
 	if (IS_IA32_PROCESS(regs))
 		child_stack->b0 = (unsigned long) &ia32_ret_from_clone;
 	else
 		child_stack->b0 = (unsigned long) &ia64_ret_from_clone;
-	child_stack->ar_bspstore = child_rbs + rbs_size;
 
 	/* copy parts of thread_struct: */
 	p->thread.ksp = (unsigned long) child_stack - 16;
@@ -358,8 +354,8 @@
 	 * therefore we must specify them explicitly here and not include them in
 	 * IA64_PSR_BITS_TO_CLEAR.
 	 */
-	child_ptregs->cr_ipsr =  ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
-			      & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
+	child_ptregs->cr_ipsr = ((child_ptregs->cr_ipsr | IA64_PSR_BITS_TO_SET)
+				 & ~(IA64_PSR_BITS_TO_CLEAR | IA64_PSR_PP | IA64_PSR_UP));
 
 	/*
 	 * NOTE: The calling convention considers all floating point
@@ -578,27 +574,43 @@
 pid_t
 kernel_thread (int (*fn)(void *), void *arg, unsigned long flags)
 {
-	struct task_struct *parent = current;
-	int result; 
-	pid_t tid;
+	extern void ia64_invoke_kernel_thread_helper (void);
+	unsigned long *helper_fptr = (unsigned long *) &ia64_invoke_kernel_thread_helper;
+	struct {
+		struct switch_stack sw;
+		struct pt_regs pt;
+	} regs;
+
+	memset(&regs, 0, sizeof(regs));
+	regs.pt.cr_iip = helper_fptr[0];	/* set entry point (IP) */
+	regs.pt.r1 = helper_fptr[1];		/* set GP */
+	regs.pt.r9 = (unsigned long) fn;	/* 1st argument */
+	regs.pt.r11 = (unsigned long) arg;	/* 2nd argument */
+	/* Preserve PSR bits, except for bits 32-34 and 37-45, which we can't read.  */
+	regs.pt.cr_ipsr = ia64_getreg(_IA64_REG_PSR) | IA64_PSR_BN;
+	regs.pt.cr_ifs = 1UL << 63;		/* mark as valid, empty frame */
+	regs.sw.ar_fpsr = regs.pt.ar_fpsr = ia64_getreg(_IA64_REG_AR_FPSR);
+	regs.sw.ar_bspstore = (unsigned long) current + IA64_RBS_OFFSET;
+
+	return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs.pt, 0, NULL, NULL);
+}
+EXPORT_SYMBOL(kernel_thread);
 
-	tid = clone(flags | CLONE_VM | CLONE_UNTRACED, 0);
-	if (parent != current) {
+/* This gets called from kernel_thread() via ia64_invoke_thread_helper().  */
+int
+kernel_thread_helper (int (*fn)(void *), void *arg)
+{
 #ifdef CONFIG_IA32_SUPPORT
-		if (IS_IA32_PROCESS(ia64_task_regs(current))) {
-			/* A kernel thread is always a 64-bit process. */
-			current->thread.map_base  = DEFAULT_MAP_BASE;
-			current->thread.task_size = DEFAULT_TASK_SIZE;
-			ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
-			ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
-		}
-#endif
-		result = (*fn)(arg);
-		_exit(result);
+	if (IS_IA32_PROCESS(ia64_task_regs(current))) {
+		/* A kernel thread is always a 64-bit process. */
+		current->thread.map_base  = DEFAULT_MAP_BASE;
+		current->thread.task_size = DEFAULT_TASK_SIZE;
+		ia64_set_kr(IA64_KR_IO_BASE, current->thread.old_iob);
+		ia64_set_kr(IA64_KR_TSSD, current->thread.old_k1);
 	}
-	return tid;
+#endif
+	return (*fn)(arg);
 }
-EXPORT_SYMBOL(kernel_thread);
 
 /*
  * Flush thread state.  This is called when a thread does an execve().
diff -Nru a/arch/ia64/mm/hugetlbpage.c b/arch/ia64/mm/hugetlbpage.c
--- a/arch/ia64/mm/hugetlbpage.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/mm/hugetlbpage.c	Sun Feb 29 12:54:28 2004
@@ -1,7 +1,11 @@
 /*
  * IA-64 Huge TLB Page Support for Kernel.
  *
- * Copyright (C) 2002, Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 2002-2004 Rohit Seth <rohit.seth@intel.com>
+ * Copyright (C) 2003-2004 Ken Chen <kenneth.w.chen@intel.com>
+ *
+ * Sep, 2003: add numa support
+ * Feb, 2004: dynamic hugetlb page size via boot parameter
  */
 
 #include <linux/config.h>
@@ -18,11 +22,10 @@
 #include <asm/tlb.h>
 #include <asm/tlbflush.h>
 
-#define TASK_HPAGE_BASE (REGION_HPAGE << REGION_SHIFT)
-
 static long	htlbpagemem;
 int		htlbpage_max;
 static long	htlbzone_pages;
+unsigned int	hpage_shift=HPAGE_SHIFT_DEFAULT;
 
 static struct list_head hugepage_freelists[MAX_NUMNODES];
 static spinlock_t htlbpage_lock = SPIN_LOCK_UNLOCKED;
@@ -407,7 +410,7 @@
 		return -EINVAL;
 	/* This code assumes that REGION_HPAGE != 0. */
 	if ((REGION_NUMBER(addr) != REGION_HPAGE) || (addr & (HPAGE_SIZE - 1)))
-		addr = TASK_HPAGE_BASE;
+		addr = HPAGE_REGION_BASE;
 	else
 		addr = ALIGN(addr, HPAGE_SIZE);
 	for (vmm = find_vma(current->mm, addr); ; vmm = vmm->vm_next) {
@@ -520,6 +523,35 @@
 }
 __setup("hugepages=", hugetlb_setup);
 
+static int __init hugetlb_setup_sz(char *str)
+{
+	u64 tr_pages;
+	unsigned long long size;
+
+	if (ia64_pal_vm_page_size(&tr_pages, NULL) != 0)
+		/*
+		 * shouldn't happen, but just in case.
+		 */
+		tr_pages = 0x15557000UL;
+
+	size = memparse(str, &str);
+	if (*str || (size & (size-1)) || !(tr_pages & size) ||
+		size <= PAGE_SIZE ||
+		size >= (1UL << PAGE_SHIFT << MAX_ORDER)) {
+		printk(KERN_WARNING "Invalid huge page size specified\n");
+		return 1;
+	}
+
+	hpage_shift = __ffs(size);
+	/*
+	 * boot cpu already executed ia64_mmu_init, and has HPAGE_SHIFT_DEFAULT
+	 * override here with new page shift.
+	 */
+	ia64_set_rr(HPAGE_REGION_BASE, hpage_shift << 2);
+	return 1;
+}
+__setup("hugepagesz=", hugetlb_setup_sz);
+
 static int __init hugetlb_init(void)
 {
 	int i;
@@ -540,7 +572,7 @@
 	printk("Total HugeTLB memory allocated, %ld\n", htlbpagemem);
 	return 0;
 }
-module_init(hugetlb_init);
+__initcall(hugetlb_init);
 
 int hugetlb_report_meminfo(char *buf)
 {
diff -Nru a/arch/ia64/mm/init.c b/arch/ia64/mm/init.c
--- a/arch/ia64/mm/init.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ia64/mm/init.c	Sun Feb 29 12:54:28 2004
@@ -342,6 +342,10 @@
 
 	ia64_tlb_init();
 
+#ifdef	CONFIG_HUGETLB_PAGE
+	ia64_set_rr(HPAGE_REGION_BASE, HPAGE_SHIFT << 2);
+#endif
+
 #ifdef	CONFIG_IA64_MCA
 	cpu = smp_processor_id();
 
diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c
--- a/arch/ppc64/kernel/prom.c	Sun Feb 29 12:54:28 2004
+++ b/arch/ppc64/kernel/prom.c	Sun Feb 29 12:54:28 2004
@@ -516,6 +516,9 @@
 	return mem;
 }
 
+#ifdef CONFIG_PMAC_DART
+static int dart_force_on;
+#endif
 
 static unsigned long __init
 prom_initialize_lmb(unsigned long mem)
@@ -539,10 +542,12 @@
 		prom_print(opt);
 		prom_print(RELOC("\n"));
 		opt += 6;
-		while(*opt && *opt == ' ')
+		while (*opt && *opt == ' ')
 			opt++;
 		if (!strncmp(opt, RELOC("off"), 3))
 			nodart = 1;
+		else if (!strncmp(opt, RELOC("force"), 5))
+			RELOC(dart_force_on) = 1;
 	}
 #else
 	nodart = 1;
@@ -763,8 +768,10 @@
 	extern unsigned long dart_tablebase;
 	extern unsigned long dart_tablesize;
 
-	/* Only reserve DART space if machine has more than 2Gb of RAM */
-	if (lmb_end_of_DRAM() <= 0x80000000ull)
+	/* Only reserve DART space if machine has more than 2GB of RAM
+	 * or if requested with iommu=on on cmdline.
+	 */
+	if (lmb_end_of_DRAM() <= 0x80000000ull && !RELOC(dart_force_on))
 		return;
 
 	/* 512 pages is max DART tablesize. */
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	Sun Feb 29 12:54:28 2004
+++ b/arch/x86_64/kernel/x8664_ksyms.c	Sun Feb 29 12:54:28 2004
@@ -196,6 +196,7 @@
 
 #ifdef CONFIG_SMP
 EXPORT_SYMBOL(cpu_sibling_map);
+EXPORT_SYMBOL(smp_num_siblings);
 #endif
 
 extern void do_softirq_thunk(void);
diff -Nru a/drivers/mtd/afs.c b/drivers/mtd/afs.c
--- a/drivers/mtd/afs.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/mtd/afs.c	Sun Feb 29 12:54:28 2004
@@ -57,6 +57,17 @@
 	u32 checksum;		/* Image checksum (inc. this struct)     */
 };
 
+static u32 word_sum(void *words, int num)
+{
+	u32 *p = words;
+	u32 sum = 0;
+
+	while (num--)
+		sum += *p++;
+
+	return sum;
+}
+
 static int
 afs_read_footer(struct mtd_info *mtd, u_int *img_start, u_int *iis_start,
 		u_int off, u_int mask)
@@ -85,6 +96,12 @@
 		ret = 0;
 
 	/*
+	 * Check the checksum.
+	 */
+	if (word_sum(&fs, sizeof(fs) / sizeof(u32)) != 0xffffffff)
+		ret = 0;
+
+	/*
 	 * Don't touch the SIB.
 	 */
 	if (fs.type == 2)
@@ -114,16 +131,35 @@
 afs_read_iis(struct mtd_info *mtd, struct image_info_struct *iis, u_int ptr)
 {
 	size_t sz;
-	int ret;
+	int ret, i;
 
 	memset(iis, 0, sizeof(*iis));
 	ret = mtd->read(mtd, ptr, sizeof(*iis), &sz, (u_char *) iis);
-	if (ret >= 0 && sz != sizeof(*iis))
-		ret = -EINVAL;
 	if (ret < 0)
-		printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n",
-			ptr, ret);
+		goto failed;
+
+	if (sz != sizeof(*iis)) {
+		ret = -EINVAL;
+		goto failed;
+	}
+
+	ret = 0;
+
+	/*
+	 * Validate the name - it must be NUL terminated.
+	 */
+	for (i = 0; i < sizeof(iis->name); i++)
+		if (iis->name[i] == '\0')
+			break;
 
+	if (i < sizeof(iis->name))
+		ret = 1;
+
+	return ret;
+
+ failed:
+	printk(KERN_ERR "AFS: mtd read failed at 0x%x: %d\n",
+		ptr, ret);
 	return ret;
 }
 
@@ -160,6 +196,8 @@
 		ret = afs_read_iis(mtd, &iis, iis_ptr);
 		if (ret < 0)
 			break;
+		if (ret == 0)
+			continue;
 
 		sz += sizeof(struct mtd_partition);
 		sz += strlen(iis.name) + 1;
@@ -194,6 +232,8 @@
 		ret = afs_read_iis(mtd, &iis, iis_ptr);
 		if (ret < 0)
 			break;
+		if (ret == 0)
+			continue;
 
 		strcpy(str, iis.name);
 		size = mtd->erasesize + off - img_ptr;
diff -Nru a/drivers/mtd/maps/integrator-flash.c b/drivers/mtd/maps/integrator-flash.c
--- a/drivers/mtd/maps/integrator-flash.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/mtd/maps/integrator-flash.c	Sun Feb 29 12:54:28 2004
@@ -1,8 +1,9 @@
 /*======================================================================
 
-    drivers/mtd/maps/armflash.c: ARM Flash Layout/Partitioning
+    drivers/mtd/maps/integrator-flash.c: ARM Integrator flash map driver
   
     Copyright (C) 2000 ARM Limited
+    Copyright (C) 2003 Deep Blue Solutions 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
@@ -21,7 +22,7 @@
    This is access code for flashes using ARM's flash partitioning 
    standards.
 
-   $Id: integrator-flash.c,v 1.12 2003/05/20 20:59:30 dwmw2 Exp $
+   $Id: integrator-flash.c,v 1.15 2004/02/27 22:37:39 rmk Exp $
 
 ======================================================================*/
 
@@ -64,7 +65,7 @@
 		info->plat->set_vpp(on);
 }
 
-static const char *probes[] = { "RedBoot", "afs", NULL };
+static const char *probes[] = { "cmdlinepart", "RedBoot", "afs", NULL };
 
 static int armflash_probe(struct device *_dev)
 {
diff -Nru a/drivers/mtd/maps/lubbock-flash.c b/drivers/mtd/maps/lubbock-flash.c
--- a/drivers/mtd/maps/lubbock-flash.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/mtd/maps/lubbock-flash.c	Sun Feb 29 12:54:28 2004
@@ -74,7 +74,7 @@
 	lubbock_maps[flashboot].name = "Lubbock Boot ROM";
 
 	for (i = 0; i < 2; i++) {
-		lubbock_maps[i].virt = (unsigned long)__ioremap(lubbock_maps[i].phys, WINDOW_SIZE, 0);
+		lubbock_maps[i].virt = (unsigned long)ioremap(lubbock_maps[i].phys, WINDOW_SIZE);
 		if (!lubbock_maps[i].virt) {
 			printk(KERN_WARNING "Failed to ioremap %s\n", lubbock_maps[i].name);
 			if (!ret)
@@ -97,8 +97,8 @@
 		}
 		mymtds[i]->owner = THIS_MODULE;
 
-		int ret = parse_mtd_partitions(mymtds[i], probes,
-					       &parsed_parts[i], 0);
+		ret = parse_mtd_partitions(mymtds[i], probes,
+					   &parsed_parts[i], 0);
 
 		if (ret > 0)
 			nr_parsed_parts[i] = ret;
diff -Nru a/drivers/pci/hotplug/Kconfig b/drivers/pci/hotplug/Kconfig
--- a/drivers/pci/hotplug/Kconfig	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/hotplug/Kconfig	Sun Feb 29 12:54:28 2004
@@ -191,7 +191,7 @@
 
 config HOTPLUG_PCI_RPA
 	tristate "RPA PCI Hotplug driver"
-	depends on HOTPLUG_PCI && PPC_PSERIES && PPC64
+	depends on HOTPLUG_PCI && PPC_PSERIES && PPC64 && !HOTPLUG_PCI_FAKE
 	help
 	  Say Y here if you have a a RPA system that supports PCI Hotplug.
 
diff -Nru a/drivers/pci/hotplug/Makefile b/drivers/pci/hotplug/Makefile
--- a/drivers/pci/hotplug/Makefile	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/hotplug/Makefile	Sun Feb 29 12:54:28 2004
@@ -25,6 +25,8 @@
 				cpqphp_ctrl.o	\
 				cpqphp_sysfs.o	\
 				cpqphp_pci.o
+cpqphp-$(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM) += cpqphp_nvram.o
+cpqphp-objs += $(cpqphp-y)
 
 ibmphp-objs		:=	ibmphp_core.o	\
 				ibmphp_ebda.o	\
@@ -49,37 +51,24 @@
 				pciehp_sysfs.o	\
 				pciehp_hpc.o
 
-shpchp-objs		:=	shpchp_core.o	\
-				shpchp_ctrl.o	\
-				shpchp_pci.o	\
-				shpchp_sysfs.o	\
-				shpchp_hpc.o
-
-ifdef CONFIG_HOTPLUG_PCI_ACPI
-  EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi
-  ifdef CONFIG_ACPI_DEBUG
-    EXTRA_CFLAGS += -DACPI_DEBUG_OUTPUT
-  endif
-endif
-
-ifeq ($(CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM),y)
-	cpqphp-objs += cpqphp_nvram.o
-endif
-
 ifeq ($(CONFIG_HOTPLUG_PCI_PCIE_PHPRM_NONACPI),y)
   pciehp-objs += pciehprm_nonacpi.o
 else
   pciehp-objs += pciehprm_acpi.o
-  EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi -I$(TOPDIR)/drivers/acpi/include 
 endif
 
+shpchp-objs		:=	shpchp_core.o	\
+				shpchp_ctrl.o	\
+				shpchp_pci.o	\
+				shpchp_sysfs.o	\
+				shpchp_hpc.o
+
 ifeq ($(CONFIG_HOTPLUG_PCI_SHPC_PHPRM_LEGACY),y)
   shpchp-objs += shpchprm_legacy.o
 else
-   ifeq ($(CONFIG_HOTPLUG_PCI_SHPC_PHPRM_NONACPI),y)
-     shpchp-objs += shpchprm_nonacpi.o
-   else
-      shpchp-objs += shpchprm_acpi.o
-      EXTRA_CFLAGS  += -D_LINUX -I$(TOPDIR)/drivers/acpi 
-   endif
+  ifeq ($(CONFIG_HOTPLUG_PCI_SHPC_PHPRM_NONACPI),y)
+    shpchp-objs += shpchprm_nonacpi.o
+  else
+    shpchp-objs += shpchprm_acpi.o
+  endif
 endif
diff -Nru a/drivers/pci/hotplug/pciehp_ctrl.c b/drivers/pci/hotplug/pciehp_ctrl.c
--- a/drivers/pci/hotplug/pciehp_ctrl.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/hotplug/pciehp_ctrl.c	Sun Feb 29 12:54:28 2004
@@ -188,11 +188,13 @@
 		/*
 		 * Card Present
 		 */
+		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		taskInfo->event_type = INT_PRESENCE_ON;
 	} else {
 		/*
 		 * Not Present
 		 */
+		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		taskInfo->event_type = INT_PRESENCE_OFF;
 	}
 
diff -Nru a/drivers/pci/hotplug/shpchp.h b/drivers/pci/hotplug/shpchp.h
--- a/drivers/pci/hotplug/shpchp.h	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/hotplug/shpchp.h	Sun Feb 29 12:54:28 2004
@@ -390,8 +390,8 @@
 		/* Sleep for up to 1 second */
 		schedule_timeout(1*HZ);
 	} else {
-		/* Sleep for up to 1.5 second */
-		schedule_timeout(1.5*HZ);
+		/* Sleep for up to 2 seconds */
+		schedule_timeout(2*HZ);
 	}
 	set_current_state(TASK_RUNNING);
 	remove_wait_queue(&ctrl->queue, &wait);
diff -Nru a/drivers/pci/hotplug/shpchp_ctrl.c b/drivers/pci/hotplug/shpchp_ctrl.c
--- a/drivers/pci/hotplug/shpchp_ctrl.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/hotplug/shpchp_ctrl.c	Sun Feb 29 12:54:28 2004
@@ -192,11 +192,13 @@
 		/*
 		 * Card Present
 		 */
+		info("Card present on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		taskInfo->event_type = INT_PRESENCE_ON;
 	} else {
 		/*
 		 * Not Present
 		 */
+		info("Card not present on Slot(%d)\n", ctrl->first_slot + hp_slot);
 		taskInfo->event_type = INT_PRESENCE_OFF;
 	}
 
diff -Nru a/drivers/pci/hotplug/shpchp_hpc.c b/drivers/pci/hotplug/shpchp_hpc.c
--- a/drivers/pci/hotplug/shpchp_hpc.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/hotplug/shpchp_hpc.c	Sun Feb 29 12:54:28 2004
@@ -1071,9 +1071,14 @@
 	if (!shpchp_poll_mode) { 
 		ctrl = (struct controller *)dev_id;
 		php_ctlr = ctrl->hpc_ctlr_handle;
-	} else 
+	} else { 
 		php_ctlr = (struct php_ctlr_state_s *) dev_id;
+		ctrl = (struct controller *)php_ctlr->callback_instance_id;
+	}
 
+	if (!ctrl)
+		return IRQ_NONE;
+	
 	if (!php_ctlr || !php_ctlr->creg)
 		return IRQ_NONE;
 
@@ -1085,18 +1090,20 @@
 	dbg("%s: shpc_isr proceeds\n", __FUNCTION__);
 	dbg("%s: intr_loc = %x\n",__FUNCTION__, intr_loc); 
 
-	/* Mask Global Interrupt Mask - see implementation note on p. 139 */
-	/* of SHPC spec rev 1.0*/
-	temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-	dbg("%s: Before masking global interrupt, temp_dword = %x\n",
-		__FUNCTION__, temp_dword); 
-	temp_dword |= 0x00000001;
-	dbg("%s: After masking global interrupt, temp_dword = %x\n",
-		__FUNCTION__, temp_dword); 
-	writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+	if(!shpchp_poll_mode) {
+		/* Mask Global Interrupt Mask - see implementation note on p. 139 */
+		/* of SHPC spec rev 1.0*/
+		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		dbg("%s: Before masking global interrupt, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		temp_dword |= 0x00000001;
+		dbg("%s: After masking global interrupt, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
 
-	intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
-	dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
+		intr_loc2 = readl(php_ctlr->creg + INTR_LOC);  
+		dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
+	}
 
 	if (intr_loc & 0x0001) {
 		/* 
@@ -1159,14 +1166,16 @@
 			dbg("%s: intr_loc2 = %x\n",__FUNCTION__, intr_loc2); 
 		}
 	}
-	/* Unmask Global Interrupt Mask */
-	temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
-	dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
-		__FUNCTION__, temp_dword); 
-	temp_dword &= 0xfffffffe;
-	dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
-		__FUNCTION__, temp_dword); 
-	writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+	if (!shpchp_poll_mode) {
+		/* Unmask Global Interrupt Mask */
+		temp_dword = readl(php_ctlr->creg + SERR_INTR_ENABLE);
+		dbg("%s: 2-Before unmasking global interrupt, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		temp_dword &= 0xfffffffe;
+		dbg("%s: 2-After unmasking global interrupt, temp_dword = %x\n",
+			__FUNCTION__, temp_dword); 
+		writel(temp_dword, php_ctlr->creg + SERR_INTR_ENABLE);
+	}
 	
 	return IRQ_HANDLED;
 }
diff -Nru a/drivers/pci/pci.c b/drivers/pci/pci.c
--- a/drivers/pci/pci.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/pci.c	Sun Feb 29 12:54:28 2004
@@ -535,11 +535,6 @@
 	return 0;
 
 err_out:
-	printk (KERN_WARNING "PCI: Unable to reserve %s region #%d:%lx@%lx for device %s\n",
-		pci_resource_flags(pdev, i) & IORESOURCE_IO ? "I/O" : "mem",
-		i + 1, /* PCI BAR # */
-		pci_resource_len(pdev, i), pci_resource_start(pdev, i),
-		pci_name(pdev));
 	while(--i >= 0)
 		pci_release_region(pdev, i);
 		
diff -Nru a/drivers/pci/probe.c b/drivers/pci/probe.c
--- a/drivers/pci/probe.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/probe.c	Sun Feb 29 12:54:28 2004
@@ -366,6 +366,8 @@
 		child = pci_alloc_child_bus(bus, dev, busnr);
 		child->primary = buses & 0xFF;
 		child->subordinate = (buses >> 16) & 0xFF;
+		child->bridge_ctl = bctl;
+
 		cmax = pci_scan_child_bus(child);
 		if (cmax > max) max = cmax;
 	} else {
@@ -400,6 +402,8 @@
 		pci_write_config_dword(dev, PCI_PRIMARY_BUS, buses);
 
 		if (!is_cardbus) {
+			child->bridge_ctl = PCI_BRIDGE_CTL_NO_ISA;
+
 			/* Now we can scan all subordinate buses... */
 			max = pci_scan_child_bus(child);
 		} else {
diff -Nru a/drivers/pci/setup-bus.c b/drivers/pci/setup-bus.c
--- a/drivers/pci/setup-bus.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/setup-bus.c	Sun Feb 29 12:54:28 2004
@@ -43,13 +43,15 @@
 #define CARDBUS_IO_SIZE		(4096)
 #define CARDBUS_MEM_SIZE	(32*1024*1024)
 
-static int __devinit
+static void __devinit
 pbus_assign_resources_sorted(struct pci_bus *bus)
 {
 	struct pci_dev *dev;
 	struct resource *res;
 	struct resource_list head, *list, *tmp;
-	int idx, found_vga = 0;
+	int idx;
+
+	bus->bridge_ctl &= ~PCI_BRIDGE_CTL_VGA;
 
 	head.next = NULL;
 	list_for_each_entry(dev, &bus->devices, bus_list) {
@@ -57,7 +59,7 @@
 
 		if (class == PCI_CLASS_DISPLAY_VGA
 				|| class == PCI_CLASS_NOT_DEFINED_VGA)
-			found_vga = 1;
+			bus->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
 
 		pdev_sort_resources(dev, &head);
 	}
@@ -70,8 +72,6 @@
 		list = list->next;
 		kfree(tmp);
 	}
-
-	return found_vga;
 }
 
 static void __devinit
@@ -211,10 +211,7 @@
 	/* Clear out the upper 32 bits of PREF base. */
 	pci_write_config_dword(bridge, PCI_PREF_BASE_UPPER32, 0);
 
-	/* Check if we have VGA behind the bridge.
-	   Enable ISA in either case (FIXME!). */
-	l = (bus->resource[0]->flags & IORESOURCE_BUS_HAS_VGA) ? 0x0c : 0x04;
-	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, l);
+	pci_write_config_word(bridge, PCI_BRIDGE_CONTROL, bus->bridge_ctl);
 }
 
 /* Check whether the bridge supports optional I/O and
@@ -498,13 +495,14 @@
 pci_bus_assign_resources(struct pci_bus *bus)
 {
 	struct pci_bus *b;
-	int found_vga = pbus_assign_resources_sorted(bus);
 	struct pci_dev *dev;
 
-	if (found_vga) {
+	pbus_assign_resources_sorted(bus);
+
+	if (bus->bridge_ctl & PCI_BRIDGE_CTL_VGA) {
 		/* Propagate presence of the VGA to upstream bridges */
 		for (b = bus; b->parent; b = b->parent) {
-			b->resource[0]->flags |= IORESOURCE_BUS_HAS_VGA;
+			b->bridge_ctl |= PCI_BRIDGE_CTL_VGA;
 		}
 	}
 	list_for_each_entry(dev, &bus->devices, bus_list) {
diff -Nru a/drivers/pci/setup-res.c b/drivers/pci/setup-res.c
--- a/drivers/pci/setup-res.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/pci/setup-res.c	Sun Feb 29 12:54:28 2004
@@ -143,8 +143,9 @@
 	}
 
 	if (ret) {
-		printk(KERN_ERR "PCI: Failed to allocate resource %d(%lx-%lx) for %s\n",
-		       resno, res->start, res->end, pci_name(dev));
+		printk(KERN_ERR "PCI: Failed to allocate %s resource #%d:%lx@%lx for %s\n",
+		       res->flags & IORESOURCE_IO ? "I/O" : "mem",
+		       resno, size, res->start, pci_name(dev));
 	} else if (resno < PCI_BRIDGE_RESOURCES) {
 		pci_update_resource(dev, res, resno);
 	}
diff -Nru a/drivers/usb/host/ohci-sa1111.c b/drivers/usb/host/ohci-sa1111.c
--- a/drivers/usb/host/ohci-sa1111.c	Sun Feb 29 12:54:28 2004
+++ b/drivers/usb/host/ohci-sa1111.c	Sun Feb 29 12:54:28 2004
@@ -105,7 +105,7 @@
 }
 #endif
 
-static void usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
+static irqreturn_t usb_hcd_sa1111_hcim_irq (int irq, void *__hcd, struct pt_regs * r)
 {
 	struct usb_hcd *hcd = __hcd;
 //	unsigned long status = sa1111_readl(hcd->regs + SA1111_USB_STATUS);
@@ -120,7 +120,7 @@
 	}
 #endif
 
-	usb_hcd_irq(irq, hcd, r);
+	return usb_hcd_irq(irq, hcd, r);
 }
 
 /*-------------------------------------------------------------------------*/
diff -Nru a/fs/hpfs/buffer.c b/fs/hpfs/buffer.c
--- a/fs/hpfs/buffer.c	Sun Feb 29 12:54:28 2004
+++ b/fs/hpfs/buffer.c	Sun Feb 29 12:54:28 2004
@@ -62,56 +62,28 @@
 
 void hpfs_lock_2inodes(struct inode *i1, struct inode *i2)
 {
-	struct hpfs_inode_info *hpfs_i1 = NULL, *hpfs_i2 = NULL;
-
-	if (!i1) {
-		if (i2) {
-			hpfs_i2 = hpfs_i(i2);
+	if (!i2 || i1 == i2) {
+		hpfs_lock_inode(i1);
+	} else if (!i1) {
+		hpfs_lock_inode(i2);
+	} else {
+		struct hpfs_inode_info *hpfs_i1 = hpfs_i(i1);
+		struct hpfs_inode_info *hpfs_i2 = hpfs_i(i2);
+		if (i1->i_ino < i2->i_ino) {
+			down(&hpfs_i1->i_sem);
+			down(&hpfs_i2->i_sem);
+		} else {
 			down(&hpfs_i2->i_sem);
-		}
-		return;
-	}
-	if (!i2) {
-		if (i1) {
-			hpfs_i1 = hpfs_i(i1);
 			down(&hpfs_i1->i_sem);
 		}
-		return;
 	}
-	if (i1->i_ino < i2->i_ino) {
-		down(&hpfs_i1->i_sem);
-		down(&hpfs_i2->i_sem);
-	} else if (i1->i_ino > i2->i_ino) {
-		down(&hpfs_i2->i_sem);
-		down(&hpfs_i1->i_sem);
-	} else down(&hpfs_i1->i_sem);
 }
 
 void hpfs_unlock_2inodes(struct inode *i1, struct inode *i2)
 {
-	struct hpfs_inode_info *hpfs_i1 = NULL, *hpfs_i2 = NULL;
-
-	if (!i1) {
-		if (i2) {
-			hpfs_i2 = hpfs_i(i2);
-			up(&hpfs_i2->i_sem);
-		}
-		return;
-	}
-	if (!i2) {
-		if (i1) {
-			hpfs_i1 = hpfs_i(i1);
-			up(&hpfs_i1->i_sem);
-		}
-		return;
-	}
-	if (i1->i_ino < i2->i_ino) {
-		up(&hpfs_i2->i_sem);
-		up(&hpfs_i1->i_sem);
-	} else if (i1->i_ino > i2->i_ino) {
-		up(&hpfs_i1->i_sem);
-		up(&hpfs_i2->i_sem);
-	} else up(&hpfs_i1->i_sem);
+	/* order of up() doesn't matter here */
+	hpfs_unlock_inode(i1);
+	hpfs_unlock_inode(i2);
 }
 
 void hpfs_lock_3inodes(struct inode *i1, struct inode *i2, struct inode *i3)
diff -Nru a/fs/locks.c b/fs/locks.c
--- a/fs/locks.c	Sun Feb 29 12:54:28 2004
+++ b/fs/locks.c	Sun Feb 29 12:54:28 2004
@@ -1699,6 +1699,8 @@
 	unlock_kernel();
 }
 
+EXPORT_SYMBOL(locks_remove_posix);
+
 /*
  * This function is called on the last close of an open file.
  */
diff -Nru a/include/asm-ia64/iosapic.h b/include/asm-ia64/iosapic.h
--- a/include/asm-ia64/iosapic.h	Sun Feb 29 12:54:28 2004
+++ b/include/asm-ia64/iosapic.h	Sun Feb 29 12:54:28 2004
@@ -45,9 +45,9 @@
 /*
  * Mask bit
  */
+
 #define	IOSAPIC_MASK_SHIFT		16
-#define	IOSAPIC_UNMASK			0
-#define	IOSAPIC_MSAK			1
+#define	IOSAPIC_MASK			(1<<IOSAPIC_MASK_SHIFT)
 
 #ifndef __ASSEMBLY__
 
diff -Nru a/include/asm-ia64/mmu_context.h b/include/asm-ia64/mmu_context.h
--- a/include/asm-ia64/mmu_context.h	Sun Feb 29 12:54:28 2004
+++ b/include/asm-ia64/mmu_context.h	Sun Feb 29 12:54:28 2004
@@ -140,8 +140,9 @@
 {
 	unsigned long rid;
 	unsigned long rid_incr = 0;
-	unsigned long rr0, rr1, rr2, rr3, rr4;
+	unsigned long rr0, rr1, rr2, rr3, rr4, old_rr4;
 
+	old_rr4 = ia64_get_rr(0x8000000000000000);
 	rid = context << 3;	/* make space for encoding the region number */
 	rid_incr = 1 << 8;
 
@@ -152,7 +153,7 @@
 	rr3 = rr0 + 3*rid_incr;
 	rr4 = rr0 + 4*rid_incr;
 #ifdef  CONFIG_HUGETLB_PAGE
-	rr4 = (rr4 & (~(0xfcUL))) | (HPAGE_SHIFT << 2);
+	rr4 = (rr4 & (~(0xfcUL))) | (old_rr4 & 0xfc);
 #endif
 
 	ia64_set_rr(0x0000000000000000, rr0);
diff -Nru a/include/asm-ia64/page.h b/include/asm-ia64/page.h
--- a/include/asm-ia64/page.h	Sun Feb 29 12:54:28 2004
+++ b/include/asm-ia64/page.h	Sun Feb 29 12:54:28 2004
@@ -37,31 +37,14 @@
 #define RGN_MAP_LIMIT	((1UL << (4*PAGE_SHIFT - 12)) - PAGE_SIZE)	/* per region addr limit */
 
 #ifdef CONFIG_HUGETLB_PAGE
+# define REGION_HPAGE		(4UL)	/* note: this is hardcoded in reload_context()!*/
+# define REGION_SHIFT		61
+# define HPAGE_REGION_BASE	(REGION_HPAGE << REGION_SHIFT)
+# define HPAGE_SHIFT		hpage_shift
+# define HPAGE_SHIFT_DEFAULT	28	/* check ia64 SDM for architecture supported size */
+# define HPAGE_SIZE		(__IA64_UL_CONST(1) << HPAGE_SHIFT)
+# define HPAGE_MASK		(~(HPAGE_SIZE - 1))
 
-# if defined(CONFIG_HUGETLB_PAGE_SIZE_4GB)
-#  define HPAGE_SHIFT	32
-# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1GB)
-#  define HPAGE_SHIFT	30
-# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256MB)
-#  define HPAGE_SHIFT	28
-# elif defined(CONFIG_HUGETLB_PAGE_SIZE_64MB)
-#  define HPAGE_SHIFT	26
-# elif defined(CONFIG_HUGETLB_PAGE_SIZE_16MB)
-#  define HPAGE_SHIFT	24
-# elif defined(CONFIG_HUGETLB_PAGE_SIZE_4MB)
-#  define HPAGE_SHIFT	22
-# elif defined(CONFIG_HUGETLB_PAGE_SIZE_1MB)
-#  define HPAGE_SHIFT	20
-# elif defined(CONFIG_HUGETLB_PAGE_SIZE_256KB)
-#  define HPAGE_SHIFT	18
-# else
-#  error Unsupported IA-64 HugeTLB Page Size!
-# endif
-
-# define REGION_HPAGE	(4UL)	/* note: this is hardcoded in mmu_context.h:reload_context()!*/
-# define REGION_SHIFT	61
-# define HPAGE_SIZE	(__IA64_UL_CONST(1) << HPAGE_SHIFT)
-# define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 # define HAVE_ARCH_HUGETLB_UNMAPPED_AREA
 # define ARCH_HAS_HUGEPAGE_ONLY_RANGE
 #endif /* CONFIG_HUGETLB_PAGE */
@@ -140,6 +123,7 @@
 # define is_hugepage_only_range(addr, len)		\
 	 (REGION_NUMBER(addr) == REGION_HPAGE &&	\
 	  REGION_NUMBER((addr)+(len)) == REGION_HPAGE)
+extern unsigned int hpage_shift;
 #endif
 
 static __inline__ int
diff -Nru a/include/asm-ia64/perfmon_default_smpl.h b/include/asm-ia64/perfmon_default_smpl.h
--- a/include/asm-ia64/perfmon_default_smpl.h	Sun Feb 29 12:54:28 2004
+++ b/include/asm-ia64/perfmon_default_smpl.h	Sun Feb 29 12:54:28 2004
@@ -59,7 +59,7 @@
  * last_reset_value member indicates the initial value of the overflowed PMD. 
  */
 typedef struct {
-        int             pid;                    /* active process at PMU interrupt point */
+        int             pid;                    /* thread id (for NPTL, this is gettid()) */
         unsigned char   reserved1[3];           /* reserved for future use */
         unsigned char   ovfl_pmd;               /* index of overflowed PMD */
 
@@ -69,7 +69,7 @@
 
         unsigned short  cpu;                    /* cpu on which the overfow occured */
         unsigned short  set;                    /* event set active when overflow ocurred   */
-        unsigned int    reserved2;              /* for future use */
+        int    		tgid;              	/* thread group id (for NPTL, this is getpid()) */
 } pfm_default_smpl_entry_t;
 
 #define PFM_DEFAULT_MAX_PMDS		64 /* how many pmds supported by data structures (sizeof(unsigned long) */
diff -Nru a/include/asm-ia64/scatterlist.h b/include/asm-ia64/scatterlist.h
--- a/include/asm-ia64/scatterlist.h	Sun Feb 29 12:54:28 2004
+++ b/include/asm-ia64/scatterlist.h	Sun Feb 29 12:54:28 2004
@@ -2,7 +2,7 @@
 #define _ASM_IA64_SCATTERLIST_H
 
 /*
- * Modified 1998-1999, 2001-2002
+ * Modified 1998-1999, 2001-2002, 2004
  *	David Mosberger-Tang <davidm@hpl.hp.com>, Hewlett-Packard Co
  */
 
@@ -15,6 +15,14 @@
 	unsigned int dma_length;
 };
 
-#define ISA_DMA_THRESHOLD	(~0UL)
+/*
+ * It used to be that ISA_DMA_THRESHOLD had something to do with the
+ * DMA-limits of ISA-devices.  Nowadays, its only remaining use (apart
+ * from the aha1542.c driver, which isn't 64-bit clean anyhow) is to
+ * tell the block-layer (via BLK_BOUNCE_ISA) what the max. physical
+ * address of a page is that is allocated with GFP_DMA.  On IA-64,
+ * that's 4GB - 1.
+ */
+#define ISA_DMA_THRESHOLD	0xffffffff
 
 #endif /* _ASM_IA64_SCATTERLIST_H */
diff -Nru a/include/linux/pci.h b/include/linux/pci.h
--- a/include/linux/pci.h	Sun Feb 29 12:54:28 2004
+++ b/include/linux/pci.h	Sun Feb 29 12:54:28 2004
@@ -468,6 +468,8 @@
 
 	char		name[48];
 
+	unsigned short  bridge_ctl;	/* manage NO_ISA/FBB/et al behaviors */
+	unsigned short  pad2;
 	struct device		*bridge;
 	struct class_device	class_dev;
 };
diff -Nru a/sound/oss/Kconfig b/sound/oss/Kconfig
--- a/sound/oss/Kconfig	Sun Feb 29 12:54:28 2004
+++ b/sound/oss/Kconfig	Sun Feb 29 12:54:28 2004
@@ -1147,7 +1147,7 @@
 	help
 	  Say Y or M if you have a Hammerfall or Hammerfall light
 	  multichannel card from RME. If you want to acess advanced
-	  features of the card, read Documentation/sound/rme96xx.
+	  features of the card, read Documentation/sound/oss/rme96xx.
 
 config SOUND_AD1980
 	tristate "AD1980 front/back switch plugin"