diff -urpNX dontdiff linux-2.6.10-rc1-bk13/Documentation/kernel-parameters.txt parisc-2.6-bk/Documentation/kernel-parameters.txt
--- linux-2.6.10-rc1-bk13/Documentation/kernel-parameters.txt	Wed Nov  3 05:57:42 2004
+++ parisc-2.6-bk/Documentation/kernel-parameters.txt	Wed Nov  3 06:18:44 2004
@@ -1278,9 +1278,6 @@ running once the system is up.
 	sym53c416=	[HW,SCSI]
 			See header of drivers/scsi/sym53c416.c.
 
-	sym53c8xx=	[HW,SCSI]
-			See Documentation/scsi/ncr53c8xx.txt.
-
 	t128=		[HW,SCSI]
 			See header of drivers/scsi/t128.c.
 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/Documentation/parisc/00-INDEX parisc-2.6-bk/Documentation/parisc/00-INDEX
--- linux-2.6.10-rc1-bk13/Documentation/parisc/00-INDEX	Fri Oct 22 15:39:44 2004
+++ parisc-2.6-bk/Documentation/parisc/00-INDEX	Wed Nov  3 06:18:44 2004
@@ -2,9 +2,16 @@
 	- this file.
 IODC.txt
 	- Documentation IODC
+	= Removed.
+
 debugging
 	- some debugging hints for real-mode code
 mm
 	- Documentation on parisc mm status
+	= Removed.
+
 registers
 	- current/planned usage of registers
+
+todo
+	- The things we need to work on...
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/Documentation/parisc/todo parisc-2.6-bk/Documentation/parisc/todo
--- linux-2.6.10-rc1-bk13/Documentation/parisc/todo	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/Documentation/parisc/todo	Wed Nov  3 06:11:18 2004
@@ -0,0 +1,83 @@
+Status 2004-08-16 :
+-------------------
+ - Merged to 2.6.8.1, boots on 712, 715, C3000, and A500
+   (AFAIK, probably every machine we used to support boots on this kernel.)
+ - Changes to the 2.4 branch are pretty much non-existant,
+   Matthew does a good job of merging from upstream though.
+ - SMP compiles, and seems to work on certain boxes.
+ - No preemptible support
+
+Todo:
+-----
+
+ - 2004-08-16 (Carlos)
+   Review the gettimeofday implementation, possibly use a
+   light-weight-syscall and rely on cr16 and cpu speed for
+   more accurate timing?
+ - CPU hotplug: we cannot bring up cpus after init, and we don't know if we can
+   shutdown cpus
+ - task_struct/thread_info split -- task_struct should not be visible in
+   entry.S, we need to move some items into thread_info -- this includes
+   pt_regs and maybe some of the flags (ptrace, etc)
+ - flush_tlb_kernel_range is horribly inefficient. this has been merged
+   with the userspace tlb flush, but it has a magic constant that needs
+   tuning
+ - syscall signal return path needs work, we don't loop on signal
+   delivery like other archs
+ - parisc is the only arch that defines __kernel_clock_t as int instead
+   of long, find out if we can use long (check compat_signals.c)
+
+ - REVIEW ALL THE TODO ENTRIES BELOW!
+
+ - the fix for do_fork needs checking
+ - our PDC early debug console hacks need to be cleaned up somehow
+ - ad1889 driver: only works with .wav;  Convert to ALSA (ggg, tausq, tbone)
+ - ns87415 dma doesn't work reliably on suckyio-systems
+ - (ab)use kmap/kunmap on 64-bit to eliminate flush_dcache calls.
+ - cp_new_stat32 for sys_parisc32.c is inefficient; maybe it's better
+   to fill in a tmp stat32 and just do copy_to_user in one go at the end?
+ - investigate not putting in extable entries for put_kernel_asm; will
+   probably reduce kernel size
+ - fix HIL problem: ksoftirqd/0 eats 56% cpu (kernel 2.4 & kernel 2.5)
+ - write floppy driver for lasi
+ - write floppy driver for suckyio
+ - spifi driver (rbrad)
+ - write optimized versions of lcopy_{to,from}_user. Can we port the
+   hpux versions?
+ - NPTL kernel support (CLONE_*TID flags need to be correctly handled by 
+   sys_clone() and friends)
+ - fix ALSA harmony driver to reflect changes in ALSA architecture.
+
+
+ Started and in progress:
+ ------------------------
+ - 2004-08-16 (Carlos)
+   64-bit binutils needs to be fixed to get multiple stub
+   section support.
+
+ - 2004-08-16 (Carlos)
+   Working on light-weight-syscall to implement atomic
+   compare and swap primitive.
+
+ - IRQ code (use arch-indep scheme & cpu-affinity support) (jejb, ggg, t-bone)
+
+ - REVIEW THE ENTRIES BELOW!
+
+ - Some options still need Kconfig help entries (see below!)
+ - Look at Config.help too. (tbone, HIL -> helge?)
+ - port hil_kbd.c to new input layer
+ - port hil_ptr.c to new input layer
+
+ - 64-bit userspace (Leandro)
+
+
+ CONFIG options without help:
+ -----------------------------
+ - REVIEW THESE ENTRIES!
+
+ _USB_OHCI_HCD (add parisc info?)
+ _HP_SDC_RTC
+ _HIL_MLC
+ _HIL_KBD (to improve)
+ _HIL_PTR (to improve)
+
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/Documentation/scsi/sym53c8xx_2.txt parisc-2.6-bk/Documentation/scsi/sym53c8xx_2.txt
--- linux-2.6.10-rc1-bk13/Documentation/scsi/sym53c8xx_2.txt	Fri Oct 22 15:38:20 2004
+++ parisc-2.6-bk/Documentation/scsi/sym53c8xx_2.txt	Wed Nov  3 06:18:45 2004
@@ -4,7 +4,9 @@ Written by Gerard Roudier <groudier@free
 21 Rue Carnot
 95170 DEUIL LA BARRE - FRANCE
 
-Decembre 28 2000
+Updated by Matthew Wilcox <matthew@wil.cx>
+
+2004-10-09
 ===============================================================================
 
 1.  Introduction
@@ -29,26 +31,20 @@ Decembre 28 2000
 10. Boot setup commands
       10.1 Syntax
       10.2 Available arguments
-             10.2.1  Master parity checking
-             10.2.2  Scsi parity checking
-             10.2.3  Default number of tagged commands
-             10.2.4  Default synchronous period factor
-             10.2.5  Verbosity level
-             10.2.6  Debug mode
-             10.2.7  Burst max
-             10.2.8  LED support
-             10.2.9  Max wide
-             10.2.10 Differential mode
-             10.2.11 IRQ mode
-             10.2.12 Reverse probe
-             10.2.13 Fix up PCI configuration space
-             10.2.14 Serial NVRAM
-             10.2.15 Check SCSI BUS 
-             10.2.16 Exclude a host from being attached
-             10.2.17 Suggest a default SCSI id for hosts
-      10.3 PCI configuration fix-up boot option
-      10.4 Serial NVRAM support boot option
-      10.5 SCSI BUS checking boot option
+             10.2.1  Default number of tagged commands
+             10.2.2  Burst max
+             10.2.3  LED support
+             10.2.4  Differential mode
+             10.2.5  IRQ mode
+             10.2.6  Check SCSI BUS 
+             10.2.7  Suggest a default SCSI id for hosts
+             10.2.8  Verbosity level
+             10.2.9  Debug mode
+             10.2.10 Settle delay
+             10.2.11 Serial NVRAM
+             10.2.12 Exclude a host from being attached
+      10.3 Converting from old options
+      10.4 SCSI BUS checking boot option
 11. SCSI problem troubleshooting
       15.1 Problem tracking
       15.2 Understanding hardware error reports
@@ -94,6 +90,9 @@ The history of this driver can be summer
       Write a glue code for Linux.
           Gerard Roudier
 
+2004: Remove FreeBSD compatibility code.  Remove support for versions of
+      Linux before 2.6.  Start using Linux facilities.
+
 This README file addresses the Linux version of the driver. Under FreeBSD, 
 the driver documentation is the sym.8 man page.
 
@@ -279,11 +278,10 @@ setting verbose level to zero, as follow
 6. Parity checking
 
 The driver supports SCSI parity checking and PCI bus master parity
-checking. These features must be enabled in order to ensure safe data
-transfers. However, some flawed devices or mother boards will have
-problems with parity. You can disable either PCI parity or SCSI parity 
-checking by entering appropriate options from the boot command line.
-(See 10: Boot setup commands).
+checking.  These features must be enabled in order to ensure safe
+data transfers.  Some flawed devices or mother boards may have problems
+with parity.  The options to defeat parity checking have been removed
+from the driver.
 
 7. Profiling information
 
@@ -428,77 +426,90 @@ Synchronous transfers frequency       (d
 
 10.1 Syntax
 
-Setup commands can be passed to the driver either at boot time or as a 
-string variable using 'insmod'.
-
-A boot setup command for this driver begins with the driver name "sym53c8xx=".
-The kernel syntax parser then expects an optionnal list of integers separated 
-with comma followed by an optional list of  comma-separated strings.
+Setup commands can be passed to the driver either at boot time or as
+parameters to modprobe, as described in Documentation/kernel-parameters.txt
 
 Example of boot setup command under lilo prompt:
 
-lilo: linux root=/dev/sda2 sym53c8xx=tags:4,sync:10,debug:0x200
+lilo: linux root=/dev/sda2 sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200
 
 - enable tagged commands, up to 4 tagged commands queued.
 - set synchronous negotiation speed to 10 Mega-transfers / second.
 - set DEBUG_NEGO flag.
 
-Since comma seems not to be allowed when defining a string variable using  
-'insmod', the driver also accepts <space> as option separator. 
-The following command will install driver module with the same options as 
-above.
+The following command will install the driver module with the same
+options as above.
 
-    insmod sym53c8xx.o sym53c8xx="tags:4 sync:10 debug:0x200"
-
-The integer list of arguments is discarded by the driver. 
-
-Each string argument must be specified as "keyword:value". Only lower-case 
-characters and digits are allowed.
+    modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200"
 
 10.2 Available arguments
 
-10.2.1  Master parity checking
-        mpar:y     enabled
-        mpar:n     disabled
-
-10.2.2  Scsi parity checking
-        spar:y     enabled
-        spar:n     disabled
-
-10.2.3  Default number of tagged commands
-        tags:0     (or tags:1 ) tagged command queuing disabled
-        tags:#tags (#tags  > 1) tagged command queuing enabled
+10.2.1  Default number of tagged commands
+        cmd_per_lun=0 (or cmd_per_lun=1) tagged command queuing disabled
+        cmd_per_lun=#tags (#tags > 1) tagged command queuing enabled
   #tags will be truncated to the max queued commands configuration parameter.
-  This option also allows to specify a command queue depth for each device 
-  that support tagged command queueing.
+
+10.2.2  Detailed control of tagged commands
+  This option allows you to specify a command queue depth for each device 
+  that supports tagged command queueing.
   Example:
-      sym53c8xx=tags:10/t2t3q16-t5q24/t1u2q32
-               will set devices queue depth as follow:
+      tag_ctrl=10/t2t3q16-t5q24/t1u2q32
+  will set devices queue depth as follow:
       - controller #0 target #2 and target #3                  -> 16 commands,
       - controller #0 target #5                                -> 24 commands,
       - controller #1 target #1 logical unit #2                -> 32 commands,
       - all other logical units (all targets, all controllers) -> 10 commands.
 
-10.2.4  Default synchronous period factor
-        sync:255     disabled (asynchronous transfer mode)
-        sync:#factor
-  #factor =  9     Ultra-3 SCSI 80 Mega-transfers / second (Wide only)
-  #factor = 10     Ultra-2 SCSI 40 Mega-transfers / second
-  #factor = 11     Ultra-2 SCSI 33 Mega-transfers / second
-  #factor < 25     Ultra   SCSI 20 Mega-transfers / second
-  #factor < 50     Fast    SCSI-2
-
-  In all cases, the driver will use the minimum transfer period supported by 
-  controllers according to SYM53C8XX chip type.
-
-10.2.5  Verbosity level
-        verb:0     minimal
-        verb:1     normal
-        verb:2     too much
-
-10.2.6 Debug mode
-        debug:0	 clear debug flags
-        debug:#x   set debug flags
+10.2.3 Burst max
+        burst=0    burst disabled
+        burst=255  get burst length from initial IO register settings.
+        burst=#x   burst enabled (1<<#x burst transfers max)
+  #x is an integer value which is log base 2 of the burst transfers max.
+  By default the driver uses the maximum value supported by the chip.
+
+10.2.4 LED support
+        led=1      enable  LED support
+        led=0      disable LED support
+  Do not enable LED support if your scsi board does not use SDMS BIOS.
+  (See 'Configuration parameters')
+
+10.2.4 Differential mode
+        diff=0	never set up diff mode
+        diff=1	set up diff mode if BIOS set it
+        diff=2	always set up diff mode
+        diff=3	set diff mode if GPIO3 is not set
+
+10.2.5 IRQ mode
+        irqm=0     always open drain
+        irqm=1     same as initial settings (assumed BIOS settings)
+        irqm=2     always totem pole
+
+10.2.6 Check SCSI BUS 
+        buschk=<option bits>
+
+    Available option bits:
+        0x0:   No check.
+        0x1:   Check and do not attach the controller on error.  
+        0x2:   Check and just warn on error.
+
+10.2.7 Suggest a default SCSI id for hosts
+        hostid=255	no id suggested.
+        hostid=#x   (0 < x < 7) x suggested for hosts SCSI id.
+
+    If a host SCSI id is available from the NVRAM, the driver will ignore 
+    any value suggested as boot option. Otherwise, if a suggested value 
+    different from 255 has been supplied, it will use it. Otherwise, it will 
+    try to deduce the value previously set in the hardware and use value 
+    7 if the hardware value is zero.
+
+10.2.8  Verbosity level
+        verb=0     minimal
+        verb=1     normal
+        verb=2     too much
+
+10.2.9 Debug mode
+        debug=0	 clear debug flags
+        debug=#x   set debug flags
   #x is an integer value combining the following power-of-2 values:
   DEBUG_ALLOC       0x1
   DEBUG_PHASE       0x2
@@ -517,55 +528,17 @@ characters and digits are allowed.
   You can play safely with DEBUG_NEGO. However, some of these flags may 
   generate bunches of syslog messages. 
 
-10.2.7 Burst max
-        burst:0    burst disabled
-        burst:255  get burst length from initial IO register settings.
-        burst:#x   burst enabled (1<<#x burst transfers max)
-  #x is an integer value which is log base 2 of the burst transfers max.
-  By default the driver uses the maximum value supported by the chip.
-
-10.2.8 LED support
-        led:1      enable  LED support
-        led:0      disable LED support
-  Donnot enable LED support if your scsi board does not use SDMS BIOS.
-  (See 'Configuration parameters')
-
-10.2.9 Max wide
-        wide:1      wide scsi enabled
-        wide:0      wide scsi disabled
-  Some scsi boards use a 875 (ultra wide) and only supply narrow connectors.
-  If you have connected a wide device with a 50 pins to 68 pins cable 
-  converter, any accepted wide negotiation will break further data transfers.
-  In such a case, using "wide:0" in the bootup command will be helpfull. 
-
-10.2.10 Differential mode
-        diff:0	never set up diff mode
-        diff:1	set up diff mode if BIOS set it
-        diff:2	always set up diff mode
-        diff:3	set diff mode if GPIO3 is not set
-
-10.2.11 IRQ mode
-        irqm:0     always open drain
-        irqm:1     same as initial settings (assumed BIOS settings)
-        irqm:2     always totem pole
-
-10.2.12 Reverse probe
-        revprob:n   probe chip ids from the PCI configuration in this order:
-                    810, 815, 825, 860, 875, 885, 875A, 895, 896, 895A,
-                    1510D, 1010-33, 1010-66.
-        revprob:y   probe chip ids in the reverse order.
-
-10.2.13 Fix up PCI configuration space
-        pcifix:<option bits>
+10.2.10 Settle delay
+        settle=n	delay for n seconds
 
-    Available option bits:
-        0x0:   No attempt to fix PCI configuration space registers values.
-        0x1:   Set PCI cache-line size register if not set.
-        0x2:   Set write and invalidate bit in PCI command register.
-
-10.2.14 Serial NVRAM
-        nvram:n     do not look for serial NVRAM
-        nvram:y     test controllers for onboard serial NVRAM
+  After a bus reset, the driver will delay for n seconds before talking
+  to any device on the bus.  The default is 3 seconds and safe mode will
+  default it to 10.
+
+10.2.11 Serial NVRAM
+	NB: option not currently implemented.
+        nvram=n     do not look for serial NVRAM
+        nvram=y     test controllers for onboard serial NVRAM
         (alternate binary form)
         nvram=<bits options>
         0x01   look for NVRAM  (equivalent to nvram=y)
@@ -574,105 +547,28 @@ characters and digits are allowed.
         0x08   ignore NVRAM "Scan at boot time" parameter for all devices
         0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
 
-10.2.15 Check SCSI BUS 
-        buschk:<option bits>
-
-    Available option bits:
-        0x0:   No check.
-        0x1:   Check and do not attach the controller on error.  
-        0x2:   Check and just warn on error.
-
-10.2.16 Exclude a host from being attached
-        excl=<io_address>
+10.2.12 Exclude a host from being attached
+        excl=<io_address>,...
 
     Prevent host at a given io address from being attached.
-    For example 'sym53c8xx=excl:0xb400,excl:0xc000' indicate to the 
+    For example 'excl=0xb400,0xc000' indicate to the 
     driver not to attach hosts at address 0xb400 and 0xc000.
 
-10.2.17 Suggest a default SCSI id for hosts
-        hostid:255	no id suggested.
-        hostid:#x   (0 < x < 7) x suggested for hosts SCSI id.
-
-    If a host SCSI id is available from the NVRAM, the driver will ignore 
-    any value suggested as boot option. Otherwise, if a suggested value 
-    different from 255 has been supplied, it will use it. Otherwise, it will 
-    try to deduce the value previously set in the hardware and use value 
-    7 if the hardware value is zero.
-
-10.3 PCI configuration fix-up boot option
-
-pcifix:<option bits>
+10.3 Converting from old style options
 
-Available option bits:
-    0x1:     Set PCI cache-line size register if not set.
-    0x2:     Set write and invalidate bit in PCI command register.
+Previously, the sym2 driver accepted arguments of the form
+	sym53c8xx=tags:4,sync:10,debug:0x200
 
-Use 'pcifix:3' in order to allow the driver to fix both PCI features.
+As a result of the new module parameters, this is no longer available.
+Most of the options have remained the same, but tags has split into
+cmd_per_lun and tag_ctrl for its two different purposes.  The sample above
+would be specified as:
+	modprobe sym53c8xx cmd_per_lun=4 sync=10 debug=0x200
 
-Recent SYMBIOS 53C8XX scsi processors are able to use PCI read multiple 
-and PCI write and invalidate commands. These features require the 
-cache line size register to be properly set in the PCI configuration 
-space of the chips. On the other hand, chips will use PCI write and 
-invalidate commands only if the corresponding bit is set to 1 in the 
-PCI command register.
+or on the kernel boot line as:
+	sym53c8xx.cmd_per_lun=4 sym53c8xx.sync=10 sym53c8xx.debug=0x200
 
-Not all PCI bioses set the PCI cache line register and the PCI write and 
-invalidate bit in the PCI configuration space of 53C8XX chips.
-Optimized PCI accesses may be broken for some PCI/memory controllers or 
-make problems with some PCI boards.
-
-10.4 Serial NVRAM support boot option
-
-nvram:n     do not look for serial NVRAM
-nvram:y     test controllers for onboard serial NVRAM
-
-This option can also been entered as an hexadecimal value that allows 
-to control what information the driver will get from the NVRAM and what 
-information it will ignore.
-For details see '17. Serial NVRAM support'.
-
-When this option is enabled, the driver tries to detect all boards using 
-a Serial NVRAM. This memory is used to hold user set up parameters.
-
-The parameters the driver is able to get from the NVRAM depend on the 
-data format used, as follow:
-
-                                 Tekram format      Symbios format
-General and host parameters
-    Boot order                         N                   Y
-    Host SCSI ID                       Y                   Y
-    SCSI parity checking               Y                   Y
-    Verbose boot messages              N                   Y
-SCSI devices parameters
-    Synchronous transfer speed         Y                   Y
-    Wide 16 / Narrow                   Y                   Y
-    Tagged Command Queuing enabled     Y                   Y
-    Disconnections enabled             Y                   Y
-    Scan at boot time                  N                   Y
-
-In order to speed up the system boot, for each device configured without 
-the "scan at boot time" option, the driver forces an error on the 
-first TEST UNIT READY command received for this device.
-
-Some SDMS BIOS revisions seem to be unable to boot cleanly with very fast 
-hard disks. In such a situation you cannot configure the NVRAM with 
-optimized parameters value.
-
-The 'nvram' boot option can be entered in hexadecimal form in order 
-to ignore some options configured in the NVRAM, as follow:
-
-nvram=<bits options>
-      0x01   look for NVRAM  (equivalent to nvram=y)
-      0x02   ignore NVRAM "Synchronous negotiation" parameters for all devices
-      0x04   ignore NVRAM "Wide negotiation"  parameter for all devices
-      0x08   ignore NVRAM "Scan at boot time" parameter for all devices
-      0x80   also attach controllers set to OFF in the NVRAM (sym53c8xx only)
-
-Option 0x80 is disabled by default.
-Result is that, by default (option not set), the sym53c8xx driver will not 
-attach controllers set to OFF in the NVRAM.
-
-10.5 SCSI BUS checking boot option.
+10.4 SCSI BUS checking boot option.
 
 When this option is set to a non-zero value, the driver checks SCSI lines 
 logic state, 100 micro-seconds after having asserted the SCSI RESET line.
@@ -805,14 +701,8 @@ serial NVRAM is used by Symbios and Tekr
 host adaptor and it's attached drives.
 
 The Symbios NVRAM also holds data on the boot order of host adaptors in a
-system with more than one host adaptor. This enables the order of scanning
-the cards for drives to be changed from the default used during host adaptor
-detection.
-
-This can be done to a limited extent at the moment using "reverse probe" but
-this only changes the order of detection of different types of cards. The
-NVRAM boot order settings can do this as well as change the order the same
-types of cards are scanned in, something "reverse probe" cannot do.
+system with more than one host adaptor.  This information is no longer used
+as it's fundamentally incompatible with the hotplug PCI model.
 
 Tekram boards using Symbios chips, DC390W/F/U, which have NVRAM are detected
 and this is used to distinguish between Symbios compatible and Tekram host 
@@ -823,6 +713,26 @@ used together with the Symbios cards usi
 "diff" support. ("led pin" support for Symbios compatible cards can remain
 enabled when using Tekram cards. It does nothing useful for Tekram host
 adaptors but does not cause problems either.)
+
+The parameters the driver is able to get from the NVRAM depend on the 
+data format used, as follow:
+
+                                 Tekram format      Symbios format
+General and host parameters
+    Boot order                         N                   Y
+    Host SCSI ID                       Y                   Y
+    SCSI parity checking               Y                   Y
+    Verbose boot messages              N                   Y
+SCSI devices parameters
+    Synchronous transfer speed         Y                   Y
+    Wide 16 / Narrow                   Y                   Y
+    Tagged Command Queuing enabled     Y                   Y
+    Disconnections enabled             Y                   Y
+    Scan at boot time                  N                   Y
+
+In order to speed up the system boot, for each device configured without 
+the "scan at boot time" option, the driver forces an error on the 
+first TEST UNIT READY command received for this device.
 
 
 17.2 Symbios NVRAM layout
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/Makefile parisc-2.6-bk/Makefile
--- linux-2.6.10-rc1-bk13/Makefile	Wed Nov  3 05:57:43 2004
+++ parisc-2.6-bk/Makefile	Wed Nov  3 06:26:02 2004
@@ -1,7 +1,7 @@
 VERSION = 2
 PATCHLEVEL = 6
 SUBLEVEL = 10
-EXTRAVERSION = -rc1-bk13
+EXTRAVERSION = -rc1-bk13-pa0
 NAME=Woozy Numbat
 
 # *DOCUMENTATION*
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/ia64/ia32/ia32_entry.S parisc-2.6-bk/arch/ia64/ia32/ia32_entry.S
--- linux-2.6.10-rc1-bk13/arch/ia64/ia32/ia32_entry.S	Fri Oct 22 15:39:40 2004
+++ parisc-2.6-bk/arch/ia64/ia32/ia32_entry.S	Wed Nov  3 06:18:47 2004
@@ -470,16 +470,16 @@ ia32_syscall_table:
 	data8 sys_remap_file_pages
 	data8 sys_set_tid_address
  	data8 sys32_timer_create
- 	data8 compat_timer_settime	/* 260 */
- 	data8 compat_timer_gettime
+ 	data8 compat_sys_timer_settime	/* 260 */
+ 	data8 compat_sys_timer_gettime
  	data8 sys_timer_getoverrun
  	data8 sys_timer_delete
- 	data8 compat_clock_settime
- 	data8 compat_clock_gettime /* 265 */
- 	data8 compat_clock_getres
- 	data8 compat_clock_nanosleep
-	data8 compat_statfs64
-	data8 compat_fstatfs64
+ 	data8 compat_sys_clock_settime
+ 	data8 compat_sys_clock_gettime /* 265 */
+ 	data8 compat_sys_clock_getres
+ 	data8 compat_sys_clock_nanosleep
+	data8 compat_sys_statfs64
+	data8 compat_sys_fstatfs64
  	data8 sys_tgkill	/* 270 */
  	data8 compat_sys_utimes
  	data8 sys32_fadvise64_64
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/kernel/drivers.c parisc-2.6-bk/arch/parisc/kernel/drivers.c
--- linux-2.6.10-rc1-bk13/arch/parisc/kernel/drivers.c	Fri Oct 22 15:40:17 2004
+++ parisc-2.6-bk/arch/parisc/kernel/drivers.c	Wed Nov  3 06:18:49 2004
@@ -10,6 +10,7 @@
  * Copyright (c) 2001 Matthew Wilcox for Hewlett Packard
  * Copyright (c) 2001 Helge Deller <deller@gmx.de>
  * Copyright (c) 2001,2002 Ryan Bradetich 
+ * Copyright (c) 2004 Thibaut VARENE <varenet@parisc-linux.org>
  * 
  * The file handles registering devices and drivers, then matching them.
  * It's the closest we get to a dating agency.
@@ -30,13 +31,16 @@
 struct hppa_dma_ops *hppa_dma_ops;
 EXPORT_SYMBOL(hppa_dma_ops);
 
-static struct parisc_device root;
+static struct device root = {
+	.bus_id = "parisc",
+};
 
-#define for_each_padev(dev) \
-	for (dev = root.child; dev != NULL; dev = next_dev(dev))
+#define for_each_padev(padev) \
+	for (padev = next_dev(&root); padev != NULL; \
+			padev = next_dev(&padev->dev))
 
-#define check_dev(dev) \
-	(dev->id.hw_type != HPHW_FAULTY) ? dev : next_dev(dev)
+#define check_dev(padev) \
+	(padev->id.hw_type != HPHW_FAULTY) ? padev : next_dev(&padev->dev)
 
 /**
  * next_dev - enumerates registered devices
@@ -45,20 +49,20 @@ static struct parisc_device root;
  * next_dev does a depth-first search of the tree, returning parents
  * before children.  Returns NULL when there are no more devices.
  */
-struct parisc_device *next_dev(struct parisc_device *dev)
+static struct parisc_device *next_dev(struct device *dev)
 {
-	if (dev->child) {
-		return check_dev(dev->child);
-	} else if (dev->sibling) {
-		return dev->sibling;
+	if (!list_empty(&dev->children)) {
+		dev = list_to_dev(dev->children.next);
+		return check_dev(to_parisc_device(dev));
 	}
 
-	/* Exhausted tree at this level, time to go up. */
-	do {
+	while (dev != &root) {
+		if (dev->node.next != &dev->parent->children) {
+			dev = list_to_dev(dev->node.next);
+			return to_parisc_device(dev);
+		}
 		dev = dev->parent;
-		if (dev && dev->sibling)
-			return dev->sibling;
-	} while (dev != &root);
+	}
 
 	return NULL;
 }
@@ -209,24 +213,58 @@ static struct parisc_device *find_device
  * Walks up the device tree looking for a device of the specified type.
  * If it finds it, it returns it.  If not, it returns NULL.
  */
-const struct parisc_device *find_pa_parent_type(const struct parisc_device *dev, int type)
+const struct parisc_device *
+find_pa_parent_type(const struct parisc_device *padev, int type)
 {
+	const struct device *dev = &padev->dev;
 	while (dev != &root) {
-		if (dev->id.hw_type == type)
-			return dev;
+		struct parisc_device *candidate = to_parisc_device(dev);
+		if (candidate->id.hw_type == type)
+			return candidate;
 		dev = dev->parent;
 	}
 
 	return NULL;
 }
 
-static void
-get_node_path(struct parisc_device *dev, struct hardware_path *path)
+#ifdef CONFIG_PCI
+static inline int is_pci_dev(struct device *dev)
+{
+	return dev->bus == &pci_bus_type;
+}
+#else
+static inline int is_pci_dev(struct device *dev)
+{
+	return 0;
+}
+#endif
+
+/*
+ * get_node_path fills in @path with the firmware path to the device.
+ * Note that if @node is a parisc device, we don't fill in the 'mod' field.
+ * This is because both callers pass the parent and fill in the mod
+ * themselves.  If @node is a PCI device, we do fill it in, even though this
+ * is inconsistent.
+ */
+static void get_node_path(struct device *dev, struct hardware_path *path)
 {
 	int i = 5;
 	memset(&path->bc, -1, 6);
+
+	if (is_pci_dev(dev)) {
+		unsigned int devfn = to_pci_dev(dev)->devfn;
+		path->mod = PCI_FUNC(devfn);
+		path->bc[i--] = PCI_SLOT(devfn);
+		dev = dev->parent;
+	}
+
 	while (dev != &root) {
-		path->bc[i--] = dev->hw_path;
+		if (is_pci_dev(dev)) {
+			unsigned int devfn = to_pci_dev(dev)->devfn;
+			path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn)<< 5);
+		} else if (dev->bus == &parisc_bus_type) {
+			path->bc[i--] = to_parisc_device(dev)->hw_path;
+		}
 		dev = dev->parent;
 	}
 }
@@ -256,7 +294,7 @@ char *print_pa_hwpath(struct parisc_devi
 {
 	struct hardware_path path;
 
-	get_node_path(dev->parent, &path);
+	get_node_path(dev->dev.parent, &path);
 	path.mod = dev->hw_path;
 	return print_hwpath(&path, output);
 }
@@ -264,33 +302,17 @@ EXPORT_SYMBOL(print_pa_hwpath);
 
 #if defined(CONFIG_PCI) || defined(CONFIG_ISA)
 /**
- * get_pci_node_path - Returns hardware path for PCI devices
- * dev: The device to return the path for
- * output: Pointer to a previously-allocated array to place the path in.
+ * get_pci_node_path - Determines the hardware path for a PCI device
+ * @pdev: The device to return the path for
+ * @path: Pointer to a previously-allocated array to place the path in.
  *
  * This function fills in the hardware_path structure with the route to
  * the specified PCI device.  This structure is suitable for passing to
  * PDC calls.
  */
-void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path)
+void get_pci_node_path(struct pci_dev *pdev, struct hardware_path *path)
 {
-	struct pci_bus *bus;
-	const struct parisc_device *padev;
-	int i = 5;
-
-	memset(&path->bc, -1, 6);
-	path->mod = PCI_FUNC(dev->devfn);
-	path->bc[i--] = PCI_SLOT(dev->devfn);
-	for (bus = dev->bus; bus->parent; bus = bus->parent) {
-		unsigned int devfn = bus->self->devfn;
-		path->bc[i--] = PCI_SLOT(devfn) | (PCI_FUNC(devfn) << 5);
-	}
-
-	padev = HBA_DATA(bus->bridge->platform_data)->dev;
-	while (padev != &root) {
-		path->bc[i--] = padev->hw_path;
-		padev = padev->parent;
-	}
+	get_node_path(&pdev->dev, path);
 }
 EXPORT_SYMBOL(get_pci_node_path);
 
@@ -314,19 +336,41 @@ EXPORT_SYMBOL(print_pci_hwpath);
 
 #endif /* defined(CONFIG_PCI) || defined(CONFIG_ISA) */
 
+static void setup_bus_id(struct parisc_device *padev)
+{
+	struct hardware_path path;
+	char *output = padev->dev.bus_id;
+	int i;
+
+	get_node_path(padev->dev.parent, &path);
+
+	for (i = 0; i < 6; i++) {
+		if (path.bc[i] == -1)
+			continue;
+		output += sprintf(output, "%u:", (unsigned char) path.bc[i]);
+	}
+	sprintf(output, "%u", (unsigned char) padev->hw_path);
+}
 
-struct parisc_device * create_tree_node(char id, struct parisc_device *parent,
-		struct parisc_device **insert)
+struct parisc_device * create_tree_node(char id, struct device *parent)
 {
 	struct parisc_device *dev = kmalloc(sizeof(*dev), GFP_KERNEL);
 	if (!dev)
 		return NULL;
+
 	memset(dev, 0, sizeof(*dev));
 	dev->hw_path = id;
 	dev->id.hw_type = HPHW_FAULTY;
-	dev->parent = parent;
-	dev->sibling = *insert;
-	*insert = dev;
+
+	dev->dev.parent = parent;
+	setup_bus_id(dev);
+
+	dev->dev.bus = &parisc_bus_type;
+	/* make the generic dma mask a pointer to the parisc one */
+	dev->dev.dma_mask = &dev->dma_mask;
+	dev->dev.coherent_dma_mask = dev->dma_mask;
+	device_register(&dev->dev);
+
 	return dev;
 }
 
@@ -338,36 +382,27 @@ struct parisc_device * create_tree_node(
  * Checks all the children of @parent for a matching @id.  If none
  * found, it allocates a new device and returns it.
  */
-struct parisc_device *
-alloc_tree_node(struct parisc_device *parent, char id)
+static struct parisc_device * alloc_tree_node(struct device *parent, char id)
 {
-	struct parisc_device *prev;
-	if ((!parent->child) || (parent->child->hw_path > id)) {
-		return create_tree_node(id, parent, &parent->child);
-	}
-
-	prev = parent->child;
-	if (prev->hw_path == id)
-		return prev;
+	struct device *dev;
 
-	while (prev->sibling && prev->sibling->hw_path < id) {
-		prev = prev->sibling;
+	list_for_each_entry(dev, &parent->children, node) {
+		struct parisc_device *padev = to_parisc_device(dev);
+		if (padev->hw_path == id)
+			return padev;
 	}
 
-	if ((prev->sibling) && (prev->sibling->hw_path == id))
-		return prev->sibling;
-
-	return create_tree_node(id, parent, &prev->sibling);
+	return create_tree_node(id, parent);
 }
 
-static struct parisc_device *find_parisc_device(struct hardware_path *modpath)
+static struct parisc_device *create_parisc_device(struct hardware_path *modpath)
 {
 	int i;
-	struct parisc_device *parent = &root;
+	struct device *parent = &root;
 	for (i = 0; i < 6; i++) {
 		if (modpath->bc[i] == -1)
 			continue;
-		parent = alloc_tree_node(parent, modpath->bc[i]);
+		parent = &alloc_tree_node(parent, modpath->bc[i])->dev;
 	}
 	return alloc_tree_node(parent, modpath->mod);
 }
@@ -389,7 +424,7 @@ alloc_pa_dev(unsigned long hpa, struct h
 	if (status != PDC_OK)
 		return NULL;
 
-	dev = find_parisc_device(mod_path);
+	dev = create_parisc_device(mod_path);
 	if (dev->id.hw_type != HPHW_FAULTY) {
 		char p[64];
 		print_pa_hwpath(dev, p);
@@ -414,7 +449,7 @@ alloc_pa_dev(unsigned long hpa, struct h
 
 static int parisc_generic_match(struct device *dev, struct device_driver *drv)
 {
-	return  match_device(to_parisc_driver(drv), to_parisc_device(dev));
+	return match_device(to_parisc_driver(drv), to_parisc_device(dev));
 }
 
 struct bus_type parisc_bus_type = {
@@ -440,6 +475,104 @@ int register_parisc_device(struct parisc
 	return 0;
 }
 
+/**
+ * match_pci_device - Matches a pci device against a given hardware path
+ * entry.
+ * @dev: the generic device (known to be contained by a pci_dev).
+ * @index: the current BC index
+ * @modpath: the hardware path.
+ * @return: true if the device matches the hardware path.
+ */
+static int match_pci_device(struct device *dev, int index,
+		struct hardware_path *modpath)
+{
+	struct pci_dev *pdev = to_pci_dev(dev);
+	int id;
+
+	if (index == 5) {
+		/* we are at the end of the path, and on the actual device */
+		unsigned int devfn = pdev->devfn;
+		return ((modpath->bc[5] == PCI_SLOT(devfn)) &&
+					(modpath->mod == PCI_FUNC(devfn)));
+	}
+
+	id = PCI_SLOT(pdev->devfn) | (PCI_FUNC(pdev->devfn) << 5);
+	return (modpath->bc[index] == id);
+}
+
+/**
+ * match_parisc_device - Matches a parisc device against a given hardware
+ * path entry.
+ * @dev: the generic device (known to be contained by a parisc_device).
+ * @index: the current BC index
+ * @modpath: the hardware path.
+ * @return: true if the device matches the hardware path.
+ */
+static int match_parisc_device(struct device *dev, int index,
+		struct hardware_path *modpath)
+{
+	struct parisc_device *curr = to_parisc_device(dev);
+	char id = (index == 6) ? modpath->mod : modpath->bc[index];
+
+	return (curr->hw_path == id);
+}
+
+/**
+ * parse_tree_node - returns a device entry in the iotree
+ * @parent: the parent node in the tree
+ * @index: the current BC index
+ * @modpath: the hardware_path struct to match a device against
+ * @return: The corresponding device if found, NULL otherwise.
+ *
+ * Checks all the children of @parent for a matching @id.  If none
+ * found, it returns NULL.
+ */
+static struct device *
+parse_tree_node(struct device *parent, int index, struct hardware_path *modpath)
+{
+	struct device *device;
+	 
+	list_for_each_entry(device, &parent->children, node) {
+		if (device->bus == &parisc_bus_type) {
+			if (match_parisc_device(device, index, modpath))
+				return device;
+		} else if (is_pci_dev(device)) {
+			if (match_pci_device(device, index, modpath))
+				return device;
+		} else if (device->bus == NULL) {
+			/* we are on a bus bridge */
+			struct device *new = parse_tree_node(device, index, modpath);
+			if (new)
+				return new;
+		}
+	}
+
+	return NULL;
+}
+
+/**
+ * hwpath_to_device - Finds the generic device corresponding to a given hardware path.
+ * @modpath: the hardware path.
+ * @return: The target device, NULL if not found.
+ */
+struct device *hwpath_to_device(struct hardware_path *modpath)
+{
+	int i;
+	struct device *parent = &root;
+	for (i = 0; i < 6; i++) {
+		if (modpath->bc[i] == -1)
+			continue;
+		parent = parse_tree_node(parent, i, modpath);
+		if (!parent)
+			return NULL;
+	}
+	if (is_pci_dev(parent)) /* pci devices already parse MOD */
+		return parent;
+	else
+		return parse_tree_node(parent, 6, modpath);
+}
+EXPORT_SYMBOL(hwpath_to_device);
+
 #define BC_PORT_MASK 0x8
 #define BC_LOWER_PORT 0x8
 
@@ -460,7 +593,7 @@ int register_parisc_device(struct parisc
 #define READ_IO_IO_HIGH(dev) (unsigned long)(signed int)__raw_readl(dev->hpa + IO_IO_HIGH)
 
 static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
-                            struct parisc_device *parent);
+                            struct device *parent);
 
 void walk_lower_bus(struct parisc_device *dev)
 {
@@ -477,7 +610,7 @@ void walk_lower_bus(struct parisc_device
 		io_io_high = (READ_IO_IO_HIGH(dev)+ ~FLEX_MASK) & FLEX_MASK;
 	}
 
-	walk_native_bus(io_io_low, io_io_high, dev);
+	walk_native_bus(io_io_low, io_io_high, &dev->dev);
 }
 
 /**
@@ -493,7 +626,7 @@ void walk_lower_bus(struct parisc_device
  * keyboard ports).  This problem is not yet solved.
  */
 static void walk_native_bus(unsigned long io_io_low, unsigned long io_io_high,
-                            struct parisc_device *parent)
+                            struct device *parent)
 {
 	int i, devices_found = 0;
 	unsigned long hpa = io_io_low;
@@ -538,18 +671,24 @@ void walk_central_bus(void)
 void fixup_child_irqs(struct parisc_device *parent, int base,
 			int (*choose_irq)(struct parisc_device *))
 {
-	struct parisc_device *dev;
+	struct device *dev;
 
-	if (!parent->child)
-		return;
+	list_for_each_entry(dev, &parent->dev.children, node) {
+		struct parisc_device *padev = to_parisc_device(dev);
 
-	for (dev = check_dev(parent->child); dev; dev = dev->sibling) {
-		int irq = choose_irq(dev);
+		int irq;
+
+		/* work-around for 715/64 and others which have parent 
+		   at path [5] and childs at path [5/0/x] */
+		if (padev->id.hw_type == HPHW_FAULTY)
+			return fixup_child_irqs(padev, base, choose_irq);
+
+		irq = choose_irq(padev);
 		if (irq > 0) {
 #ifdef __LP64__
 			irq += 32;
 #endif
-			dev->irq = base + irq;
+			padev->irq = base + irq;
 		}
 	}
 }
@@ -573,68 +712,14 @@ static void print_parisc_device(struct p
 	printk("\n");
 }
 
-void print_subdevices(struct parisc_device *parent)
-{
-	struct parisc_device *dev;
-	for (dev = parent->child; dev != parent->sibling; dev = next_dev(dev)) {
-		print_parisc_device(dev);
-	}
-}
-
-
-/*
- * parisc_generic_device_register_recursive() - internal function to recursively
- * 	register all parisc devices
- */
-static void parisc_generic_device_register_recursive( struct parisc_device *dev )
-{
-	char tmp1[32];
-	
-	/* has this device been registered already ? */
-	if (dev->dev.dma_mask != NULL)
-		return;
-	
-	/* register all parents recursively */
-	if (dev->parent && dev->parent!=&root)
-		parisc_generic_device_register_recursive(dev->parent);
-	
-	/* set up the generic device tree for this */
-	snprintf(tmp1, sizeof(tmp1), "%d", dev->hw_path);
-	if (dev->parent && dev->parent != &root) {
-		struct parisc_device *ndev;
-		char tmp2[32];
-
-		dev->dev.parent = &dev->parent->dev;
-		for(ndev = dev->parent; ndev != &root;
-		    ndev = ndev->parent) {
-			snprintf(tmp2, sizeof(tmp2), "%d:%s",
-				 ndev->hw_path, tmp1);
-			strlcpy(tmp1, tmp2, sizeof(tmp1));
-		}
-	}
-
-	dev->dev.bus = &parisc_bus_type;
-	snprintf(dev->dev.bus_id, sizeof(dev->dev.bus_id), "parisc%s",
-		 tmp1);
-	/* make the generic dma mask a pointer to the parisc one */
-	dev->dev.dma_mask = &dev->dma_mask;
-	dev->dev.coherent_dma_mask = dev->dma_mask;
-	pr_debug("device_register(%s)\n", dev->dev.bus_id);
-	device_register(&dev->dev);
-}
-
-/*
- * parisc_generic_device_register() - register all parisc devices
+/**
+ * init_parisc_bus - Some preparation to be done before inventory
  */
-void parisc_generic_device_register(void)
+void init_parisc_bus(void)
 {
-	struct parisc_device *dev;
-	
 	bus_register(&parisc_bus_type);
-
-	for_each_padev(dev) {
-		parisc_generic_device_register_recursive( dev );
-	}
+	device_register(&root);
+	get_device(&root);
 }
 
 /**
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/kernel/firmware.c parisc-2.6-bk/arch/parisc/kernel/firmware.c
--- linux-2.6.10-rc1-bk13/arch/parisc/kernel/firmware.c	Wed Nov  3 07:57:06 2004
+++ parisc-2.6-bk/arch/parisc/kernel/firmware.c	Wed Nov  3 06:18:49 2004
@@ -11,6 +11,7 @@
  * Copyright 1999 The Puffin Group, (Alex deVries, David Kennedy)
  * Copyright 2003 Grant Grundler <grundler parisc-linux org>
  * Copyright 2003,2004 Ryan Bradetich <rbrad@parisc-linux.org>
+ * Copyright 2004 Thibaut VARENE <varenet@parisc-linux.org>
  *
  *    This program is free software; you can redistribute it and/or modify
  *    it under the terms of the GNU General Public License as published by
@@ -573,14 +574,118 @@ int pdc_lan_station_id(char *lan_addr, u
 }
 EXPORT_SYMBOL(pdc_lan_station_id);
 
+/**
+ * pdc_stable_read - Read data from Stable Storage.
+ * @staddr: Stable Storage address to access.
+ * @memaddr: The memory address where Stable Storage data shall be copied.
+ * @count: number of bytes to transfert. count is multiple of 4.
+ *
+ * This PDC call reads from the Stable Storage address supplied in staddr
+ * and copies count bytes to the memory address memaddr.
+ * The call will fail if staddr+count > PDC_STABLE size.
+ */
+int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count)
+{
+       int retval;
+
+       spin_lock_irq(&pdc_lock);
+       retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_READ, staddr,
+               __pa(pdc_result), count);
+       convert_to_wide(pdc_result);
+       memcpy(memaddr, pdc_result, count);
+       spin_unlock_irq(&pdc_lock);
+
+       return retval;
+}
+EXPORT_SYMBOL(pdc_stable_read);
+
+/**
+ * pdc_stable_write - Write data to Stable Storage.
+ * @staddr: Stable Storage address to access.
+ * @memaddr: The memory address where Stable Storage data shall be read from.
+ * @count: number of bytes to transfert. count is multiple of 4.
+ *
+ * This PDC call reads count bytes from the supplied memaddr address,
+ * and copies count bytes to the Stable Storage address staddr.
+ * The call will fail if staddr+count > PDC_STABLE size.
+ */
+int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count)
+{
+       int retval;
+
+       spin_lock_irq(&pdc_lock);
+       memcpy(pdc_result, memaddr, count);
+       convert_to_wide(pdc_result);
+       retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_WRITE, staddr,
+               __pa(pdc_result), count);
+       spin_unlock_irq(&pdc_lock);
+
+       return retval;
+}
+EXPORT_SYMBOL(pdc_stable_write);
+
+/**
+ * pdc_stable_get_size - Get Stable Storage size in bytes.
+ * @size: pointer where the size will be stored.
+ *
+ * This PDC call returns the number of bytes in the processor's Stable
+ * Storage, which is the number of contiguous bytes implemented in Stable
+ * Storage starting from staddr=0. size in an unsigned 64-bit integer
+ * which is a multiple of four.
+ */
+int pdc_stable_get_size(unsigned long *size)
+{
+       int retval;
+
+       spin_lock_irq(&pdc_lock);
+       retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_RETURN_SIZE, __pa(pdc_result));
+       *size = pdc_result[0];
+       spin_unlock_irq(&pdc_lock);
+
+       return retval;
+}
+EXPORT_SYMBOL(pdc_stable_get_size);
+
+/**
+ * pdc_stable_verify_contents - Checks that Stable Storage contents are valid.
+ *
+ * This PDC call is meant to be used to check the integrity of the current
+ * contents of Stable Storage.
+ */
+int pdc_stable_verify_contents(void)
+{
+       int retval;
+
+       spin_lock_irq(&pdc_lock);
+       retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_VERIFY_CONTENTS);
+       spin_unlock_irq(&pdc_lock);
+
+       return retval;
+}
+EXPORT_SYMBOL(pdc_stable_verify_contents);
+
+/**
+ * pdc_stable_initialize - Sets Stable Storage contents to zero and initialize
+ * the validity indicator.
+ *
+ * This PDC call will erase all contents of Stable Storage. Use with care!
+ */
+int pdc_stable_initialize(void)
+{
+       int retval;
+
+       spin_lock_irq(&pdc_lock);
+       retval = mem_pdc_call(PDC_STABLE, PDC_STABLE_INITIALIZE);
+       spin_unlock_irq(&pdc_lock);
+
+       return retval;
+}
+EXPORT_SYMBOL(pdc_stable_initialize);
 
 /**
  * pdc_get_initiator - Get the SCSI Interface Card params (SCSI ID, SDTR, SE or LVD)
  * @hwpath: fully bc.mod style path to the device.
- * @scsi_id: what someone told firmware the ID should be.
- * @period: time in cycles 
- * @width: 8 or 16-bit wide bus
- * @mode: 0,1,2 -> SE,HVD,LVD signalling mode
+ * @initiator: the array to return the result into
  *
  * Get the SCSI operational parameters from PDC.
  * Needed since HPUX never used BIOS or symbios card NVRAM.
@@ -591,8 +696,7 @@ EXPORT_SYMBOL(pdc_lan_station_id);
  *    o cable too long (ie SE scsi 10Mhz won't support 6m length),
  *    o bus width exported is less than what the interface chip supports.
  */
-int pdc_get_initiator(struct hardware_path *hwpath, unsigned char *scsi_id,
-		unsigned long *period, char *width, char *mode)
+int pdc_get_initiator(struct hardware_path *hwpath, struct pdc_initiator *initiator)
 {
 	int retval;
 
@@ -604,44 +708,38 @@ int pdc_get_initiator(struct hardware_pa
 
 	retval = mem_pdc_call(PDC_INITIATOR, PDC_GET_INITIATOR, 
 			      __pa(pdc_result), __pa(hwpath));
-
 	if (retval < PDC_OK)
-		goto fail;
-
-	*scsi_id = (unsigned char) pdc_result[0];
+		goto out;
 
-	/* convert Bus speed in Mhz to period (in 1/10 ns) */
-	switch (pdc_result[1]) {
-		/*
-		 * case  0:   driver determines rate
-		 * case -1:   Settings are uninitialized.
-		 */
-		case  5:  *period = 2000; break;
-		case 10:  *period = 1000; break;
-		case 20:  *period = 500; break;
-		case 40:  *period = 250; break;
-		case 80:  *period = 125; break;
-		default: /* Do nothing */ break;
+	if (pdc_result[0] < 16) {
+		initiator->host_id = pdc_result[0];
+	} else {
+		initiator->host_id = -1;
 	}
 
-	/* 
-	 * pdc_result[2]	PDC suggested SCSI id
-	 * pdc_result[3]	PDC suggested SCSI rate
+	/*
+	 * Sprockets and Piranha return 20 or 40 (MT/s).  Prelude returns
+	 * 1, 2, 5 or 10 for 5, 10, 20 or 40 MT/s, respectively
 	 */
+	switch (pdc_result[1]) {
+		case  1: initiator->factor = 50; break;
+		case  2: initiator->factor = 25; break;
+		case  5: initiator->factor = 12; break;
+		case 25: initiator->factor = 10; break;
+		case 20: initiator->factor = 12; break;
+		case 40: initiator->factor = 10; break;
+		default: initiator->factor = -1; break;
+	}
 
 	if (IS_SPROCKETS()) {
-		/* 0 == 8-bit, 1 == 16-bit */
-		*width = (char) pdc_result[4];
-
-		/* ...in case someone needs it in the future.
-		 * sym53c8xx.c comments say it can't autodetect
-		 * for 825/825A/875 chips.
-		 *	0 == SE, 1 == HVD, 2 == LVD
-		 */
-		*mode = (char) pdc_result[5]; 
+		initiator->width = pdc_result[4];
+		initiator->mode = pdc_result[5];
+	} else {
+		initiator->width = -1;
+		initiator->mode = -1;
 	}
 
- fail:
+ out:
 	spin_unlock_irq(&pdc_lock);
 	return (retval >= PDC_OK);
 }
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/kernel/inventory.c parisc-2.6-bk/arch/parisc/kernel/inventory.c
--- linux-2.6.10-rc1-bk13/arch/parisc/kernel/inventory.c	Fri Oct 22 15:38:17 2004
+++ parisc-2.6-bk/arch/parisc/kernel/inventory.c	Wed Nov  3 06:18:49 2004
@@ -518,7 +518,7 @@ add_system_map_addresses(struct parisc_d
 }
 
 /**
- * do_system_map_inventory - Retrieve firmware devices via SYSTEM_MAP.
+ * system_map_inventory - Retrieve firmware devices via SYSTEM_MAP.
  *
  * This function attempts to retrieve and register all the devices firmware
  * knows about via the SYSTEM_MAP PDC call.
@@ -528,16 +528,18 @@ static void __init system_map_inventory(
 	int i;
 	long status = PDC_OK;
     
-	for (i = 0; status != PDC_BAD_PROC && status != PDC_NE_MOD; i++) {
+	for (i = 0; i < 256; i++) {
 		struct parisc_device *dev;
 		struct pdc_system_map_mod_info module_result;
 		struct pdc_module_path module_path;
 
 		status = pdc_system_map_find_mods(&module_result,
 				&module_path, i);
+		if ((status == PDC_BAD_PROC) || (status == PDC_NE_MOD))
+			break;
 		if (status != PDC_OK)
 			continue;
-		
+
 		dev = alloc_pa_dev(module_result.mod_addr, &module_path.path);
 		if (!dev)
 			continue;
@@ -584,10 +586,10 @@ void __init do_memory_inventory(void)
 
 void __init do_device_inventory(void)
 {
-	extern void parisc_generic_device_register(void);
-
 	printk(KERN_INFO "Searching for devices...\n");
 
+	init_parisc_bus();
+
 	switch (pdc_type) {
 
 	case PDC_TYPE_PAT:
@@ -605,7 +607,6 @@ void __init do_device_inventory(void)
 	default:
 		panic("Unknown PDC type!\n");
 	}
-	parisc_generic_device_register();
 	printk(KERN_INFO "Found devices:\n");
 	print_parisc_devices();
 }
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/kernel/parisc_ksyms.c parisc-2.6-bk/arch/parisc/kernel/parisc_ksyms.c
--- linux-2.6.10-rc1-bk13/arch/parisc/kernel/parisc_ksyms.c	Wed Nov  3 05:57:43 2004
+++ parisc-2.6-bk/arch/parisc/kernel/parisc_ksyms.c	Wed Nov  3 06:18:50 2004
@@ -87,9 +87,9 @@ EXPORT_SYMBOL($global$);
 #include <asm/io.h>
 EXPORT_SYMBOL(__ioremap);
 EXPORT_SYMBOL(iounmap);
-EXPORT_SYMBOL(__memcpy_toio);
-EXPORT_SYMBOL(__memcpy_fromio);
-EXPORT_SYMBOL(__memset_io);
+EXPORT_SYMBOL(memcpy_toio);
+EXPORT_SYMBOL(memcpy_fromio);
+EXPORT_SYMBOL(memset_io);
 
 #include <asm/unistd.h>
 EXPORT_SYMBOL(sys_open);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/lib/Makefile parisc-2.6-bk/arch/parisc/lib/Makefile
--- linux-2.6.10-rc1-bk13/arch/parisc/lib/Makefile	Wed Nov  3 05:57:43 2004
+++ parisc-2.6-bk/arch/parisc/lib/Makefile	Wed Nov  3 06:26:51 2004
@@ -4,4 +4,6 @@
 
 lib-y	:= lusercopy.o bitops.o checksum.o io.o memset.o fixup.o memcpy.o
 
+obj-y	:= iomap.o
+
 lib-$(CONFIG_SMP) += debuglocks.o
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/lib/io.c parisc-2.6-bk/arch/parisc/lib/io.c
--- linux-2.6.10-rc1-bk13/arch/parisc/lib/io.c	Fri Oct 22 15:38:20 2004
+++ parisc-2.6-bk/arch/parisc/lib/io.c	Wed Nov  3 06:18:52 2004
@@ -15,24 +15,24 @@
  * Assumes the device can cope with 32-bit transfers.  If it can't,
  * don't use this function.
  */
-void __memcpy_toio(unsigned long dest, unsigned long src, int count)
+void memcpy_toio(volatile void __iomem *dst, const void *src, int count)
 {
-	if ((dest & 3) != (src & 3))
+	if (((unsigned long)dst & 3) != ((unsigned long)src & 3))
 		goto bytecopy;
-	while (dest & 3) {
-		writeb(*(char *)src, dest++);
+	while ((unsigned long)dst & 3) {
+		writeb(*(char *)src, dst++);
 		src++;
 		count--;
 	}
 	while (count > 3) {
-		__raw_writel(*(u32 *)src, dest);
+		__raw_writel(*(u32 *)src, dst);
 		src += 4;
-		dest += 4;
+		dst += 4;
 		count -= 4;
 	}
  bytecopy:
 	while (count--) {
-		writeb(*(char *)src, dest++);
+		writeb(*(char *)src, dst++);
 		src++;
 	}
 }
@@ -50,51 +50,51 @@ void __memcpy_toio(unsigned long dest, u
 **      Minimize total number of transfers at cost of CPU cycles.
 **	TODO: only look at src alignment and adjust the stores to dest.
 */
-void __memcpy_fromio(unsigned long dest, unsigned long src, int count)
+void memcpy_fromio(void *dst, volatile void __iomem *src, int count)
 {
 	/* first compare alignment of src/dst */ 
-	if ( ((dest ^ src) & 1) || (count < 2) )
+	if ( (((unsigned long)dst ^ (unsigned long)src) & 1) || (count < 2) )
 		goto bytecopy;
 
-	if ( ((dest ^ src) & 2) || (count < 4) )
+	if ( (((unsigned long)dst ^ (unsigned long)src) & 2) || (count < 4) )
 		goto shortcopy;
 
 	/* Then check for misaligned start address */
-	if (src & 1) {
-		*(u8 *)dest = readb(src);
+	if ((unsigned long)src & 1) {
+		*(u8 *)dst = readb(src);
 		src++;
-		dest++;
+		dst++;
 		count--;
 		if (count < 2) goto bytecopy;
 	}
 
-	if (src & 2) {
-		*(u16 *)dest = __raw_readw(src);
+	if ((unsigned long)src & 2) {
+		*(u16 *)dst = __raw_readw(src);
 		src += 2;
-		dest += 2;
+		dst += 2;
 		count -= 2;
 	}
 
 	while (count > 3) {
-		*(u32 *)dest = __raw_readl(src);
-		dest += 4;
+		*(u32 *)dst = __raw_readl(src);
+		dst += 4;
 		src += 4;
 		count -= 4;
 	}
 
  shortcopy:
 	while (count > 1) {
-		*(u16 *)dest = __raw_readw(src);
+		*(u16 *)dst = __raw_readw(src);
 		src += 2;
-		dest += 2;
+		dst += 2;
 		count -= 2;
 	}
 
  bytecopy:
 	while (count--) {
-		*(char *)dest = readb(src);
+		*(char *)dst = readb(src);
 		src++;
-		dest++;
+		dst++;
 	}
 }
 
@@ -102,20 +102,20 @@ void __memcpy_fromio(unsigned long dest,
  * Assumes the device can cope with 32-bit transfers.  If it can't,
  * don't use this function.
  */
-void __memset_io(unsigned long dest, char fill, int count)
+void memset_io(volatile void __iomem *addr, unsigned char val, int count)
 {
-	u32 fill32 = (fill << 24) | (fill << 16) | (fill << 8) | fill;
-	while (dest & 3) {
-		writeb(fill, dest++);
+	u32 val32 = (val << 24) | (val << 16) | (val << 8) | val;
+	while ((unsigned long)addr & 3) {
+		writeb(val, addr++);
 		count--;
 	}
 	while (count > 3) {
-		__raw_writel(fill32, dest);
-		dest += 4;
+		__raw_writel(val32, addr);
+		addr += 4;
 		count -= 4;
 	}
 	while (count--) {
-		writeb(fill, dest++);
+		writeb(val, addr++);
 	}
 }
 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/lib/iomap.c parisc-2.6-bk/arch/parisc/lib/iomap.c
--- linux-2.6.10-rc1-bk13/arch/parisc/lib/iomap.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/arch/parisc/lib/iomap.c	Wed Nov  3 06:11:40 2004
@@ -0,0 +1,418 @@
+/*
+ * iomap.c - Implement iomap interface for PA-RISC
+ * Copyright (c) 2004 Matthew Wilcox
+ */
+
+#include <linux/ioport.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+
+/*
+ * The iomap space on 32-bit PA-RISC is intended to look like this:
+ * 00000000-7fffffff virtual mapped IO
+ * 80000000-8fffffff ISA/EISA port space that can't be virtually mapped
+ * 90000000-9fffffff Dino port space
+ * a0000000-afffffff Astro port space
+ * b0000000-bfffffff PAT port space
+ * c0000000-cfffffff non-swapped memory IO
+ * f0000000-ffffffff legacy IO memory pointers
+ *
+ * For the moment, here's what it looks like:
+ * 80000000-8fffffff All ISA/EISA port space
+ * f0000000-ffffffff legacy IO memory pointers
+ *
+ * On 64-bit, everything is extended, so:
+ * 8000000000000000-8fffffffffffffff All ISA/EISA port space
+ * f000000000000000-ffffffffffffffff legacy IO memory pointers
+ */
+
+/*
+ * Technically, this should be 'if (VMALLOC_START < addr < VMALLOC_END),
+ * but that's slow and we know it'll be within the first 2GB.
+ */
+#ifdef CONFIG_64BIT
+#define INDIRECT_ADDR(addr)	(((unsigned long)(addr) & 1UL<<63) != 0)
+#define ADDR_TO_REGION(addr)    (((unsigned long)addr >> 60) & 7)
+#define IOPORT_MAP_BASE		(8UL << 60)
+#else
+#define INDIRECT_ADDR(addr)     (((unsigned long)(addr) & 1UL<<31) != 0)
+#define ADDR_TO_REGION(addr)    (((unsigned long)addr >> 28) & 7)
+#define IOPORT_MAP_BASE		(8UL << 28)
+#endif
+
+struct iomap_ops {
+	unsigned int (*read8)(void __iomem *);
+	unsigned int (*read16)(void __iomem *);
+	unsigned int (*read32)(void __iomem *);
+	void (*write8)(u8, void __iomem *);
+	void (*write16)(u16, void __iomem *);
+	void (*write32)(u32, void __iomem *);
+	void (*read8r)(void __iomem *, void *, unsigned long);
+	void (*read16r)(void __iomem *, void *, unsigned long);
+	void (*read32r)(void __iomem *, void *, unsigned long);
+	void (*write8r)(void __iomem *, const void *, unsigned long);
+	void (*write16r)(void __iomem *, const void *, unsigned long);
+	void (*write32r)(void __iomem *, const void *, unsigned long);
+};
+
+/* Generic ioport ops.  To be replaced later by specific dino/elroy/wax code */
+
+#define ADDR2PORT(addr) ((unsigned long __force)(addr) & 0xffffff)
+
+static unsigned int ioport_read8(void __iomem *addr)
+{
+	return inb(ADDR2PORT(addr));
+}
+
+static unsigned int ioport_read16(void __iomem *addr)
+{
+	return inw(ADDR2PORT(addr));
+}
+
+static unsigned int ioport_read32(void __iomem *addr)
+{
+	return inl(ADDR2PORT(addr));
+}
+
+static void ioport_write8(u8 datum, void __iomem *addr)
+{
+	outb(datum, ADDR2PORT(addr));
+}
+
+static void ioport_write16(u16 datum, void __iomem *addr)
+{
+	outw(datum, ADDR2PORT(addr));
+}
+
+static void ioport_write32(u32 datum, void __iomem *addr)
+{
+	outl(datum, ADDR2PORT(addr));
+}
+
+static void ioport_read8r(void __iomem *addr, void *dst, unsigned long count)
+{
+	insb(ADDR2PORT(addr), dst, count);
+}
+
+static void ioport_read16r(void __iomem *addr, void *dst, unsigned long count)
+{
+	insw(ADDR2PORT(addr), dst, count);
+}
+
+static void ioport_read32r(void __iomem *addr, void *dst, unsigned long count)
+{
+	insl(ADDR2PORT(addr), dst, count);
+}
+
+static void ioport_write8r(void __iomem *addr, const void *s, unsigned long n)
+{
+	outsb(ADDR2PORT(addr), s, n);
+}
+
+static void ioport_write16r(void __iomem *addr, const void *s, unsigned long n)
+{
+	outsw(ADDR2PORT(addr), s, n);
+}
+
+static void ioport_write32r(void __iomem *addr, const void *s, unsigned long n)
+{
+	outsl(ADDR2PORT(addr), s, n);
+}
+
+static const struct iomap_ops ioport_ops = {
+	ioport_read8,
+	ioport_read16,
+	ioport_read32,
+	ioport_write8,
+	ioport_write16,
+	ioport_write32,
+	ioport_read8r,
+	ioport_read16r,
+	ioport_read32r,
+	ioport_write8r,
+	ioport_write16r,
+	ioport_write32r,
+};
+
+/* Legacy I/O memory ops */
+
+static unsigned int iomem_read8(void __iomem *addr)
+{
+	return readb(addr);
+}
+
+static unsigned int iomem_read16(void __iomem *addr)
+{
+	return readw(addr);
+}
+
+static unsigned int iomem_read32(void __iomem *addr)
+{
+	return readl(addr);
+}
+
+static void iomem_write8(u8 datum, void __iomem *addr)
+{
+	writeb(datum, addr);
+}
+
+static void iomem_write16(u16 datum, void __iomem *addr)
+{
+	writew(datum, addr);
+}
+
+static void iomem_write32(u32 datum, void __iomem *addr)
+{
+	writel(datum, addr);
+}
+
+static void iomem_read8r(void __iomem *addr, void *dst, unsigned long count)
+{
+	while (count--) {
+		*(u8 *)dst = __raw_readb(addr);
+		dst++;
+	}
+}
+
+static void iomem_read16r(void __iomem *addr, void *dst, unsigned long count)
+{
+	while (count--) {
+		*(u16 *)dst = __raw_readw(addr);
+		dst += 2;
+	}
+}
+
+static void iomem_read32r(void __iomem *addr, void *dst, unsigned long count)
+{
+	while (count--) {
+		*(u32 *)dst = __raw_readl(addr);
+		dst += 4;
+	}
+}
+
+static void iomem_write8r(void __iomem *addr, const void *s, unsigned long n)
+{
+	while (n--) {
+		__raw_writeb(*(u8 *)s, addr);
+		s++;
+	}
+}
+
+static void iomem_write16r(void __iomem *addr, const void *s, unsigned long n)
+{
+	while (n--) {
+		__raw_writew(*(u16 *)s, addr);
+		s += 2;
+	}
+}
+
+static void iomem_write32r(void __iomem *addr, const void *s, unsigned long n)
+{
+	while (n--) {
+		__raw_writel(*(u32 *)s, addr);
+		s += 4;
+	}
+}
+
+static const struct iomap_ops iomem_ops = {
+	iomem_read8,
+	iomem_read16,
+	iomem_read32,
+	iomem_write8,
+	iomem_write16,
+	iomem_write32,
+	iomem_read8r,
+	iomem_read16r,
+	iomem_read32r,
+	iomem_write8r,
+	iomem_write16r,
+	iomem_write32r,
+};
+
+const struct iomap_ops *iomap_ops[8] = {
+	[0] = &ioport_ops,
+	[7] = &iomem_ops
+};
+
+
+unsigned int ioread8(void __iomem *addr)
+{
+	if (unlikely(INDIRECT_ADDR(addr)))
+		return iomap_ops[ADDR_TO_REGION(addr)]->read8(addr);
+	return *((u8 *)addr);
+}
+
+unsigned int ioread16(void __iomem *addr)
+{
+	if (unlikely(INDIRECT_ADDR(addr)))
+		return iomap_ops[ADDR_TO_REGION(addr)]->read16(addr);
+	return le16_to_cpup((u16 *)addr);
+}
+
+unsigned int ioread32(void __iomem *addr)
+{
+	if (unlikely(INDIRECT_ADDR(addr)))
+		return iomap_ops[ADDR_TO_REGION(addr)]->read32(addr);
+	return le32_to_cpup((u32 *)addr);
+}
+
+void iowrite8(u8 datum, void __iomem *addr)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->write8(datum, addr);
+	} else {
+		*((u8 *)addr) = datum;
+	}
+}
+
+void iowrite16(u16 datum, void __iomem *addr)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->write16(datum, addr);
+	} else {
+		*((u16 *)addr) = cpu_to_le16(datum);
+	}
+}
+
+void iowrite32(u32 datum, void __iomem *addr)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->write32(datum, addr);
+	} else {
+		*((u32 *)addr) = cpu_to_le32(datum);
+	}
+}
+
+/* Repeating interfaces */
+
+void ioread8_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->read8r(addr, dst, count);
+	} else {
+		while (count--) {
+			*(u8 *)dst = *(u8 *)addr;
+			dst++;
+		}
+	}
+}
+
+void ioread16_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->read16r(addr, dst, count);
+	} else {
+		while (count--) {
+			*(u16 *)dst = *(u16 *)addr;
+			dst += 2;
+		}
+	}
+}
+
+void ioread32_rep(void __iomem *addr, void *dst, unsigned long count)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->read32r(addr, dst, count);
+	} else {
+		while (count--) {
+			*(u32 *)dst = *(u32 *)addr;
+			dst += 4;
+		}
+	}
+}
+
+void iowrite8_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->write8r(addr, src, count);
+	} else {
+		while (count--) {
+			*(u8 *)addr = *(u8 *)src;
+			src++;
+		}
+	}
+}
+
+void iowrite16_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->write16r(addr, src, count);
+	} else {
+		while (count--) {
+			*(u16 *)addr = *(u16 *)src;
+			src += 2;
+		}
+	}
+}
+
+void iowrite32_rep(void __iomem *addr, const void *src, unsigned long count)
+{
+	if (unlikely(INDIRECT_ADDR(addr))) {
+		iomap_ops[ADDR_TO_REGION(addr)]->write32r(addr, src, count);
+	} else {
+		while (count--) {
+			*(u32 *)addr = *(u32 *)src;
+			src += 4;
+		}
+	}
+}
+
+/* Mapping interfaces */
+
+void __iomem *ioport_map(unsigned long port, unsigned int nr)
+{
+	return (void __iomem *)(IOPORT_MAP_BASE | port);
+}
+
+void ioport_unmap(void __iomem *addr)
+{
+	if (!INDIRECT_ADDR(addr)) {
+		iounmap(addr);
+	}
+}
+
+/* Create a virtual mapping cookie for a PCI BAR (memory or IO) */
+void __iomem *pci_iomap(struct pci_dev *dev, int bar, unsigned long maxlen)
+{
+	unsigned long start = pci_resource_start(dev, bar);
+	unsigned long len = pci_resource_len(dev, bar);
+	unsigned long flags = pci_resource_flags(dev, bar);
+
+	if (!len || !start)
+		return NULL;
+	if (maxlen && len > maxlen)
+		len = maxlen;
+	if (flags & IORESOURCE_IO)
+		return ioport_map(start, len);
+	if (flags & IORESOURCE_MEM) {
+		if (flags & IORESOURCE_CACHEABLE)
+			return ioremap(start, len);
+		return ioremap_nocache(start, len);
+	}
+	/* What? */
+	return NULL;
+}
+
+void pci_iounmap(struct pci_dev *dev, void __iomem * addr)
+{
+	if (!INDIRECT_ADDR(addr)) {
+		iounmap(addr);
+	}
+}
+
+EXPORT_SYMBOL(ioread8);
+EXPORT_SYMBOL(ioread16);
+EXPORT_SYMBOL(ioread32);
+EXPORT_SYMBOL(iowrite8);
+EXPORT_SYMBOL(iowrite16);
+EXPORT_SYMBOL(iowrite32);
+EXPORT_SYMBOL(ioread8_rep);
+EXPORT_SYMBOL(ioread16_rep);
+EXPORT_SYMBOL(ioread32_rep);
+EXPORT_SYMBOL(iowrite8_rep);
+EXPORT_SYMBOL(iowrite16_rep);
+EXPORT_SYMBOL(iowrite32_rep);
+EXPORT_SYMBOL(ioport_map);
+EXPORT_SYMBOL(ioport_unmap);
+EXPORT_SYMBOL(pci_iomap);
+EXPORT_SYMBOL(pci_iounmap);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/parisc/mm/ioremap.c parisc-2.6-bk/arch/parisc/mm/ioremap.c
--- linux-2.6.10-rc1-bk13/arch/parisc/mm/ioremap.c	Fri Oct 22 15:38:54 2004
+++ parisc-2.6-bk/arch/parisc/mm/ioremap.c	Wed Nov  3 06:18:52 2004
@@ -107,7 +107,7 @@ static int remap_area_pages(unsigned lon
  * have to convert them into an offset in a page-aligned mapping, but the
  * caller shouldn't need to know that small detail.
  */
-void * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
+void __iomem * __ioremap(unsigned long phys_addr, unsigned long size, unsigned long flags)
 {
 #if !(USE_HPPA_IOREMAP)
 
@@ -118,7 +118,7 @@ void * __ioremap(unsigned long phys_addr
 		phys_addr |= 0xfc000000;
 	}
 
-	return (void *)phys_addr;
+	return (void __iomem *)phys_addr;
 
 #else
 	void * addr;
@@ -163,16 +163,16 @@ void * __ioremap(unsigned long phys_addr
 		vfree(addr);
 		return NULL;
 	}
-	return (void *) (offset + (char *)addr);
+	return (void __iomem *) (offset + (char *)addr);
 #endif
 }
 
-void iounmap(void *addr)
+void iounmap(void __iomem *addr)
 {
 #if !(USE_HPPA_IOREMAP)
 	return;
 #else
 	if (addr > high_memory)
-		return vfree((void *) (PAGE_MASK & (unsigned long) addr));
+		return vfree((void *) (PAGE_MASK & (unsigned long __force) addr));
 #endif
 }
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/ppc64/kernel/misc.S parisc-2.6-bk/arch/ppc64/kernel/misc.S
--- linux-2.6.10-rc1-bk13/arch/ppc64/kernel/misc.S	Wed Nov  3 05:57:44 2004
+++ parisc-2.6-bk/arch/ppc64/kernel/misc.S	Wed Nov  3 06:18:53 2004
@@ -935,27 +935,27 @@ _GLOBAL(sys_call_table32)
 	.llong .sys_epoll_wait
 	.llong .sys_remap_file_pages
 	.llong .ppc32_timer_create	/* 240 */
-	.llong .compat_timer_settime
-	.llong .compat_timer_gettime
+	.llong .compat_sys_timer_settime
+	.llong .compat_sys_timer_gettime
 	.llong .sys_timer_getoverrun
 	.llong .sys_timer_delete
-	.llong .compat_clock_settime	/* 245 */
-	.llong .compat_clock_gettime
-	.llong .compat_clock_getres
-	.llong .compat_clock_nanosleep
+	.llong .compat_sys_clock_settime	/* 245 */
+	.llong .compat_sys_clock_gettime
+	.llong .compat_sys_clock_getres
+	.llong .compat_sys_clock_nanosleep
 	.llong .ppc32_swapcontext
 	.llong .sys32_tgkill		/* 250 */
 	.llong .sys32_utimes
-	.llong .compat_statfs64
-	.llong .compat_fstatfs64
+	.llong .compat_sys_statfs64
+	.llong .compat_sys_fstatfs64
 	.llong .ppc32_fadvise64_64	/* 32bit only fadvise64_64 */
 	.llong .ppc_rtas		/* 255 */
 	.llong .sys_ni_syscall		/* 256 reserved for sys_debug_setcontext */
 	.llong .sys_ni_syscall		/* 257 reserved for vserver */
 	.llong .sys_ni_syscall		/* 258 reserved for new sys_remap_file_pages */
-	.llong .compat_mbind
-	.llong .compat_get_mempolicy	/* 260 */
-	.llong .compat_set_mempolicy
+	.llong .compat_sys_mbind
+	.llong .compat_sys_get_mempolicy	/* 260 */
+	.llong .compat_sys_set_mempolicy
 	.llong .compat_sys_mq_open
 	.llong .sys_mq_unlink
 	.llong .compat_sys_mq_timedsend
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/s390/kernel/compat_wrapper.S parisc-2.6-bk/arch/s390/kernel/compat_wrapper.S
--- linux-2.6.10-rc1-bk13/arch/s390/kernel/compat_wrapper.S	Fri Oct 22 15:40:29 2004
+++ parisc-2.6-bk/arch/s390/kernel/compat_wrapper.S	Wed Nov  3 06:18:53 2004
@@ -1262,19 +1262,19 @@ sys32_fadvise64_64_wrapper:
 sys32_clock_settime_wrapper:
 	lgfr	%r2,%r2			# clockid_t (int)
 	llgtr	%r3,%r3			# struct compat_timespec *
-	jg	compat_clock_settime
+	jg	compat_sys_clock_settime
 
 	.globl	sys32_clock_gettime_wrapper
 sys32_clock_gettime_wrapper:
 	lgfr	%r2,%r2			# clockid_t (int)
 	llgtr	%r3,%r3			# struct compat_timespec *
-	jg	compat_clock_gettime
+	jg	compat_sys_clock_gettime
 
 	.globl	sys32_clock_getres_wrapper
 sys32_clock_getres_wrapper:
 	lgfr	%r2,%r2			# clockid_t (int)
 	llgtr	%r3,%r3			# struct compat_timespec *
-	jg	compat_clock_getres
+	jg	compat_sys_clock_getres
 
 	.globl	sys32_clock_nanosleep_wrapper
 sys32_clock_nanosleep_wrapper:
@@ -1282,7 +1282,7 @@ sys32_clock_nanosleep_wrapper:
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# struct compat_timespec *
 	llgtr	%r5,%r5			# struct compat_timespec *
-	jg	compat_clock_nanosleep
+	jg	compat_sys_clock_nanosleep
 
 	.globl	sys32_timer_create_wrapper
 sys32_timer_create_wrapper:
@@ -1297,13 +1297,13 @@ sys32_timer_settime_wrapper:
 	lgfr	%r3,%r3			# int
 	llgtr	%r4,%r4			# struct compat_itimerspec *
 	llgtr	%r5,%r5			# struct compat_itimerspec *
-	jg	compat_timer_settime
+	jg	compat_sys_timer_settime
 
 	.globl	sys32_timer_gettime_wrapper
 sys32_timer_gettime_wrapper:
 	lgfr	%r2,%r2			# timer_t (int)
 	llgtr	%r3,%r3			# struct compat_itimerspec *
-	jg	compat_timer_gettime
+	jg	compat_sys_timer_gettime
 
 	.globl	sys32_timer_getoverrun_wrapper
 sys32_timer_getoverrun_wrapper:
@@ -1354,14 +1354,14 @@ compat_sys_statfs64_wrapper:
 	llgtr	%r2,%r2			# const char *
 	llgfr	%r3,%r3			# compat_size_t
 	llgtr	%r4,%r4			# struct compat_statfs64 *
-	jg	compat_statfs64
+	jg	compat_sys_statfs64
 
 	.globl compat_sys_fstatfs64_wrapper
 compat_sys_fstatfs64_wrapper:
 	llgfr	%r2,%r2			# unsigned int fd
 	llgfr	%r3,%r3			# compat_size_t
 	llgtr	%r4,%r4			# struct compat_statfs64 *
-	jg	compat_fstatfs64
+	jg	compat_sys_fstatfs64
 
 	.globl	compat_sys_mq_open_wrapper
 compat_sys_mq_open_wrapper:
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/sparc64/kernel/sys32.S parisc-2.6-bk/arch/sparc64/kernel/sys32.S
--- linux-2.6.10-rc1-bk13/arch/sparc64/kernel/sys32.S	Fri Oct 22 15:38:39 2004
+++ parisc-2.6-bk/arch/sparc64/kernel/sys32.S	Wed Nov  3 06:18:54 2004
@@ -84,9 +84,9 @@ SIGN2(sys32_fadvise64_64, compat_sys_fad
 SIGN2(sys32_bdflush, sys_bdflush, %o0, %o1)
 SIGN1(sys32_mlockall, sys_mlockall, %o0)
 SIGN1(sys32_nfsservctl, compat_sys_nfsservctl, %o0)
-SIGN1(sys32_clock_settime, compat_clock_settime, %o1)
-SIGN1(sys32_clock_nanosleep, compat_clock_nanosleep, %o1)
-SIGN1(sys32_timer_settime, compat_timer_settime, %o1)
+SIGN1(sys32_clock_settime, compat_sys_clock_settime, %o1)
+SIGN1(sys32_clock_nanosleep, compat_sys_clock_nanosleep, %o1)
+SIGN1(sys32_timer_settime, compat_sys_timer_settime, %o1)
 SIGN1(sys32_io_submit, compat_sys_io_submit, %o1)
 SIGN1(sys32_mq_open, compat_sys_mq_open, %o1)
 SIGN1(sys32_select, compat_sys_select, %o0)
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/sparc64/kernel/systbls.S parisc-2.6-bk/arch/sparc64/kernel/systbls.S
--- linux-2.6.10-rc1-bk13/arch/sparc64/kernel/systbls.S	Wed Nov  3 05:57:44 2004
+++ parisc-2.6-bk/arch/sparc64/kernel/systbls.S	Wed Nov  3 06:18:54 2004
@@ -60,19 +60,19 @@ sys_call_table32:
 	.word sys32_setpgid, sys32_fremovexattr, sys32_tkill, sys32_exit_group, sparc64_newuname
 /*190*/	.word sys32_init_module, sparc64_personality, sys_remap_file_pages, sys32_epoll_create, sys32_epoll_ctl
 	.word sys32_epoll_wait, sys_nis_syscall, sys_getppid, sys32_sigaction, sys_sgetmask
-/*200*/	.word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_old_readdir
+/*200*/	.word sys32_ssetmask, sys_sigsuspend, compat_sys_newlstat, sys_uselib, compat_sys_old_readdir
 	.word sys32_readahead, sys32_socketcall, sys32_syslog, sys32_lookup_dcookie, sys32_fadvise64
 /*210*/	.word sys32_fadvise64_64, sys32_tgkill, sys32_waitpid, sys_swapoff, sys32_sysinfo
 	.word sys32_ipc, sys32_sigreturn, sys_clone, sys_nis_syscall, sys32_adjtimex
 /*220*/	.word sys32_sigprocmask, sys_ni_syscall, sys32_delete_module, sys_ni_syscall, sys32_getpgid
 	.word sys32_bdflush, sys32_sysfs, sys_nis_syscall, sys32_setfsuid16, sys32_setfsgid16
-/*230*/	.word sys32_select, sys_time, sys_nis_syscall, sys_stime, compat_statfs64
-	.word compat_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
+/*230*/	.word sys32_select, sys_time, sys_nis_syscall, sys_stime, compat_sys_statfs64
+	.word compat_sys_fstatfs64, sys_llseek, sys_mlock, sys_munlock, sys32_mlockall
 /*240*/	.word sys_munlockall, sys32_sched_setparam, sys32_sched_getparam, sys32_sched_setscheduler, sys32_sched_getscheduler
 	.word sys_sched_yield, sys32_sched_get_priority_max, sys32_sched_get_priority_min, sys32_sched_rr_get_interval, compat_sys_nanosleep
 /*250*/	.word sys32_mremap, sys32_sysctl, sys32_getsid, sys_fdatasync, sys32_nfsservctl
-	.word sys_ni_syscall, sys32_clock_settime, compat_clock_gettime, compat_clock_getres, sys32_clock_nanosleep
-/*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_timer_gettime, sys_timer_getoverrun
+	.word sys_ni_syscall, sys32_clock_settime, compat_sys_clock_gettime, compat_sys_clock_getres, sys32_clock_nanosleep
+/*260*/	.word compat_sys_sched_getaffinity, compat_sys_sched_setaffinity, sys32_timer_settime, compat_sys_timer_gettime, sys_timer_getoverrun
 	.word sys_timer_delete, sys32_timer_create, sys_ni_syscall, compat_sys_io_setup, sys_io_destroy
 /*270*/	.word sys32_io_submit, sys_io_cancel, compat_sys_io_getevents, sys32_mq_open, sys_mq_unlink
 	.word sys_mq_timedsend, sys_mq_timedreceive, compat_sys_mq_notify, compat_sys_mq_getsetattr, compat_sys_waitid
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/arch/x86_64/ia32/ia32entry.S parisc-2.6-bk/arch/x86_64/ia32/ia32entry.S
--- linux-2.6.10-rc1-bk13/arch/x86_64/ia32/ia32entry.S	Wed Nov  3 05:57:44 2004
+++ parisc-2.6-bk/arch/x86_64/ia32/ia32entry.S	Wed Nov  3 06:18:55 2004
@@ -562,22 +562,22 @@ ia32_sys_call_table:
 	.quad sys_remap_file_pages
 	.quad sys_set_tid_address
 	.quad sys32_timer_create
-	.quad compat_timer_settime	/* 260 */
-	.quad compat_timer_gettime
+	.quad compat_sys_timer_settime	/* 260 */
+	.quad compat_sys_timer_gettime
 	.quad sys_timer_getoverrun
 	.quad sys_timer_delete
-	.quad compat_clock_settime
-	.quad compat_clock_gettime	/* 265 */
-	.quad compat_clock_getres
-	.quad compat_clock_nanosleep
-	.quad compat_statfs64
-	.quad compat_fstatfs64
+	.quad compat_sys_clock_settime
+	.quad compat_sys_clock_gettime	/* 265 */
+	.quad compat_sys_clock_getres
+	.quad compat_sys_clock_nanosleep
+	.quad compat_sys_statfs64
+	.quad compat_sys_fstatfs64
 	.quad sys_tgkill		/* 270 */
 	.quad compat_sys_utimes
 	.quad sys32_fadvise64_64
 	.quad quiet_ni_syscall	/* sys_vserver */
 	.quad sys_mbind
-	.quad compat_get_mempolicy	/* 275 */
+	.quad compat_sys_get_mempolicy	/* 275 */
 	.quad sys_set_mempolicy
 	.quad compat_sys_mq_open
 	.quad sys_mq_unlink
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/conflicts parisc-2.6-bk/conflicts
--- linux-2.6.10-rc1-bk13/conflicts	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/conflicts	Wed Nov  3 06:19:51 2004
@@ -0,0 +1,10 @@
+Makefile
+arch/parisc/kernel/cache.c
+arch/parisc/kernel/head.S
+arch/parisc/lib/Makefile
+drivers/parisc/lba_pci.c
+drivers/serial/8250_gsc.c
+drivers/video/stifb.c
+include/asm-parisc/io.h
+kernel/sys.c
+mm/shmem.c
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/ide/pci/ns87415.c parisc-2.6-bk/drivers/ide/pci/ns87415.c
--- linux-2.6.10-rc1-bk13/drivers/ide/pci/ns87415.c	Fri Oct 22 15:39:07 2004
+++ parisc-2.6-bk/drivers/ide/pci/ns87415.c	Wed Nov  3 06:19:00 2004
@@ -4,6 +4,7 @@
  * Copyright (C) 1997-1998	Mark Lord <mlord@pobox.com>
  * Copyright (C) 1998		Eddie C. Dost <ecd@skynet.be>
  * Copyright (C) 1999-2000	Andre Hedrick <andre@linux-ide.org>
+ * Copyright (C) 2004		Grant Grundler <grundler at parisc-linux.org>
  *
  * Inspired by an earlier effort from David S. Miller <davem@redhat.com>
  */
@@ -25,6 +26,75 @@
 
 #include <asm/io.h>
 
+#ifdef CONFIG_SUPERIO
+/* SUPERIO 87560 is a PoS chip that NatSem denies exists.
+ * Unfortunately, it's built-in on all Astro-based PA-RISC workstations
+ * which use the integrated NS87514 cell for CD-ROM support.
+ * i.e we have to support for CD-ROM installs.
+ * See drivers/parisc/superio.c for more gory details.
+ */
+#include <asm/superio.h>
+
+static unsigned long superio_ide_status[2];
+static unsigned long superio_ide_select[2];
+static unsigned long superio_ide_dma_status[2];
+
+#define SUPERIO_IDE_MAX_RETRIES 25
+
+/* Because of a defect in Super I/O, all reads of the PCI DMA status 
+ * registers, IDE status register and the IDE select register need to be 
+ * retried
+ */
+static u8 superio_ide_inb (unsigned long port)
+{
+	if (port == superio_ide_status[0] ||
+	    port == superio_ide_status[1] ||
+	    port == superio_ide_select[0] ||
+	    port == superio_ide_select[1] ||
+	    port == superio_ide_dma_status[0] ||
+	    port == superio_ide_dma_status[1]) {
+		u8 tmp;
+		int retries = SUPERIO_IDE_MAX_RETRIES;
+
+		/* printk(" [ reading port 0x%x with retry ] ", port); */
+
+		do {
+			tmp = inb(port);
+			if (tmp == 0)
+				udelay(50);
+		} while (tmp == 0 && retries-- > 0);
+
+		return tmp;
+	}
+
+	return inb(port);
+}
+
+static void __devinit superio_ide_init_iops (struct hwif_s *hwif)
+{
+	u32 base, dmabase;
+	u8 tmp;
+	struct pci_dev *pdev = hwif->pci_dev;
+	u8 port = hwif->channel;
+
+	base = pci_resource_start(pdev, port * 2) & ~3;
+	dmabase = pci_resource_start(pdev, 4) & ~3;
+
+	superio_ide_status[port] = base + IDE_STATUS_OFFSET;
+	superio_ide_select[port] = base + IDE_SELECT_OFFSET;
+	superio_ide_dma_status[port] = dmabase + (!port ? 2 : 0xa);
+	
+	/* Clear error/interrupt, enable dma */
+	tmp = superio_ide_inb(superio_ide_dma_status[port]);
+	outb(tmp | 0x66, superio_ide_dma_status[port]);
+
+	/* We need to override inb to workaround a SuperIO errata */
+	hwif->INB = superio_ide_inb;
+}
+#else
+static void __devinit superio_ide_init_iops (struct hwif_s *hwif) {}
+#endif
+
 static unsigned int ns87415_count = 0, ns87415_control[MAX_HWIFS] = { 0 };
 
 /*
@@ -119,6 +189,16 @@ static int ns87415_ide_dma_check (ide_dr
 	return __ide_dma_check(drive);
 }
 
+static void __init init_iops_ns87415(ide_hwif_t *hwif)
+{
+#ifdef CONFIG_PARISC
+	if (PCI_SLOT(hwif->pci_dev->devfn) == 0xE) {
+		/* Built-in - assume it's under superio. */
+		superio_ide_init_iops(hwif);
+	}
+#endif
+}
+
 static void __init init_hwif_ns87415 (ide_hwif_t *hwif)
 {
 	struct pci_dev *dev = hwif->pci_dev;
@@ -132,10 +212,6 @@ static void __init init_hwif_ns87415 (id
 	hwif->autodma = 0;
 	hwif->selectproc = &ns87415_selectproc;
 
-	/* Set a good latency timer and cache line size value. */
-	(void) pci_write_config_byte(dev, PCI_LATENCY_TIMER, 64);
-	/* FIXME: use pci_set_master() to ensure good latency timer value */
-
 	/*
 	 * We cannot probe for IRQ: both ports share common IRQ on INTA.
 	 * Also, leave IRQ masked during drive probing, to prevent infinite
@@ -205,6 +281,7 @@ static void __init init_hwif_ns87415 (id
 
 static ide_pci_device_t ns87415_chipset __devinitdata = {
 	.name		= "NS87415",
+	.init_iops	= init_iops_ns87415,
 	.init_hwif	= init_hwif_ns87415,
 	.channels	= 2,
 	.autodma	= AUTODMA,
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/keyboard/Kconfig parisc-2.6-bk/drivers/input/keyboard/Kconfig
--- linux-2.6.10-rc1-bk13/drivers/input/keyboard/Kconfig	Fri Oct 22 15:40:28 2004
+++ parisc-2.6-bk/drivers/input/keyboard/Kconfig	Wed Nov  3 06:19:01 2004
@@ -29,6 +29,44 @@ config KEYBOARD_ATKBD
 	  To compile this driver as a module, choose M here: the
 	  module will be called atkbd.
 
+config KEYBOARD_ATKBD_HP_KEYCODES
+	bool "Use HP keyboard scancodes"
+	depends on PARISC && KEYBOARD_ATKBD
+	default y
+	help
+	  Say Y here if you have a PA-RISC machine and want to use an AT or
+	  PS/2 keyboard, and your keyboard uses keycodes that are specific to
+	  PA-RISC keyboards.
+
+	  Say N if you use a standard keyboard.
+
+config KEYBOARD_ATKBD_RDI_KEYCODES
+	bool "Use PrecisionBook keyboard scancodes"
+	depends on KEYBOARD_ATKBD_HP_KEYCODES
+	default n
+	help
+	  If you have an RDI PrecisionBook, say Y here if you want to use its
+	  built-in keyboard (as opposed to an external keyboard).
+
+	  The PrecisionBook has five keys that conflict with those used by most
+	  AT and PS/2 keyboards. These are as follows:
+
+	    PrecisionBook    Standard AT or PS/2
+
+	    F1               F12
+	    Left Ctrl        Left Alt
+	    Caps Lock        Left Ctrl
+	    Right Ctrl       Caps Lock
+	    Left             102nd key (the key to the right of Left Shift)
+
+	  If you say N here, and use the PrecisionBook keyboard, then each key
+	  in the left-hand column will be interpreted as the corresponding key
+	  in the right-hand column.
+
+	  If you say Y here, and use an external keyboard, then each key in the
+	  right-hand column will be interpreted as the key shown in the
+	  left-hand column.
+
 config KEYBOARD_SUNKBD
 	tristate "Sun Type 4 and Type 5 keyboard support"
 	depends on INPUT && INPUT_KEYBOARD
@@ -96,3 +134,34 @@ config KEYBOARD_AMIGA
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called amikbd.
+
+config KEYBOARD_HIL_OLD
+	tristate "HP HIL keyboard support (simple driver)"
+	depends on GSC && INPUT && INPUT_KEYBOARD && !HIL_MLC
+	default y
+	help
+	  The "Human Interface Loop" is a older, 8-channel USB-like
+	  controller used in several Hewlett Packard models. This driver
+	  was adapted from the one written for m68k/hp300, and implements
+	  support for a keyboard attached to the HIL port, but not for
+	  any other types of HIL input devices like mice or tablets.
+	  However, it has been thoroughly tested and is stable.
+
+	  If you want full HIL support including support for multiple
+	  keyboards, mices and tablets, you have to enable the
+	  "HP System Device Controller i8042 Support" in the input/serio
+	  submenu.
+
+config KEYBOARD_HIL
+	tristate "HP HIL keyboard support"
+	depends on GSC && INPUT && INPUT_KEYBOARD
+	default y
+	select HP_SDC
+ 	select HIL_MLC
+	select SERIO
+	help
+	  The "Human Interface Loop" is a older, 8-channel USB-like
+	  controller used in several Hewlett Packard models.
+	  This driver implements support for HIL-keyboards attached
+	  to your machine, so normally you should say Y here.
+
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/keyboard/Makefile parisc-2.6-bk/drivers/input/keyboard/Makefile
--- linux-2.6.10-rc1-bk13/drivers/input/keyboard/Makefile	Fri Oct 22 15:40:36 2004
+++ parisc-2.6-bk/drivers/input/keyboard/Makefile	Wed Nov  3 06:19:01 2004
@@ -2,8 +2,6 @@
 # Makefile for the input core drivers.
 #
 
-# Each configuration option enables a list of files.
-
 obj-$(CONFIG_KEYBOARD_ATKBD)		+= atkbd.o
 obj-$(CONFIG_KEYBOARD_MAPLE)		+= maple_keyb.o
 obj-$(CONFIG_KEYBOARD_SUNKBD)		+= sunkbd.o
@@ -12,3 +10,5 @@ obj-$(CONFIG_KEYBOARD_XTKBD)		+= xtkbd.o
 obj-$(CONFIG_KEYBOARD_AMIGA)		+= amikbd.o
 obj-$(CONFIG_KEYBOARD_NEWTON)		+= newtonkbd.o
 obj-$(CONFIG_KEYBOARD_98KBD)		+= 98kbd.o
+obj-$(CONFIG_KEYBOARD_HIL)		+= hil_kbd.o
+obj-$(CONFIG_KEYBOARD_HIL_OLD)		+= hilkbd.o
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/keyboard/atkbd.c parisc-2.6-bk/drivers/input/keyboard/atkbd.c
--- linux-2.6.10-rc1-bk13/drivers/input/keyboard/atkbd.c	Fri Oct 22 15:40:36 2004
+++ parisc-2.6-bk/drivers/input/keyboard/atkbd.c	Wed Nov  3 06:19:01 2004
@@ -70,12 +70,15 @@ __obsolete_setup("atkbd_softrepeat=");
  * are loadable via an userland utility.
  */
 
-#if defined(__hppa__)
-#include "hpps2atkbd.h"
-#else
-
 static unsigned char atkbd_set2_keycode[512] = {
 
+#ifdef CONFIG_KEYBOARD_ATKBD_HP_KEYCODES
+
+/* XXX: need a more general approach */
+
+#include "hpps2atkbd.h"	/* include the keyboard scancodes */
+
+#else
 	  0, 67, 65, 63, 61, 59, 60, 88,  0, 68, 66, 64, 62, 15, 41,117,
 	  0, 56, 42, 93, 29, 16,  2,  0,  0,  0, 44, 31, 30, 17,  3,  0,
 	  0, 46, 45, 32, 18,  5,  4, 95,  0, 57, 47, 33, 20, 19,  6,183,
@@ -95,9 +98,8 @@ static unsigned char atkbd_set2_keycode[
 	110,111,108,112,106,103,  0,119,  0,118,109,  0, 99,104,119,  0,
 
 	  0,  0,  0, 65, 99,
-};
-
 #endif
+};
 
 static unsigned char atkbd_set3_keycode[512] = {
 
@@ -252,8 +254,8 @@ static irqreturn_t atkbd_interrupt(struc
 	int scroll = 0, click = -1;
 	int value;
 
-#ifdef ATKBD_DEBUG
-	printk(KERN_DEBUG "atkbd.c: Received %02x flags %02x\n", data, flags);
+#if 0 || defined(ATKBD_DEBUG)   /* CHANGEME */
+	printk(KERN_ERR "atkbd.c: Received %02x flags %02x\n", data, flags);
 #endif
 
 #if !defined(__i386__) && !defined (__x86_64__)
@@ -412,6 +414,9 @@ static irqreturn_t atkbd_interrupt(struc
 					break;
 			}
 
+#if 0  /* CHANGEME */
+			printk(KERN_ERR "Reporting: %#x, emul=%d\n", code, atkbd->emul);
+#endif
 			atkbd_report_key(&atkbd->dev, regs, atkbd->keycode[code], value);
 	}
 
@@ -645,7 +650,12 @@ static int atkbd_probe(struct atkbd *atk
  * controller may confuse the keyboard need a full reset of the keyboard. On
  * these systems the BIOS also usually doesn't do it for us.
  */
-
+/* XXX: I think this is wrong. We can't assume, that this definitively is a
+        keyboard. Since we are still in probing phase, it could be a mouse or 
+	anything else and just sending a ATKBD_CMD_RESET_BAT might confuse the
+	device. IMHO those lines should be moved to the end of atkbd_probe().
+	Helge Deller
+ */
 	if (atkbd_reset)
 		if (atkbd_command(atkbd, NULL, ATKBD_CMD_RESET_BAT))
 			printk(KERN_WARNING "atkbd.c: keyboard reset failed on %s\n", atkbd->serio->phys);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/keyboard/hil_kbd.c parisc-2.6-bk/drivers/input/keyboard/hil_kbd.c
--- linux-2.6.10-rc1-bk13/drivers/input/keyboard/hil_kbd.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/drivers/input/keyboard/hil_kbd.c	Wed Nov  3 06:12:03 2004
@@ -0,0 +1,375 @@
+/*
+ * Generic linux-input device driver for keyboard devices
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#define PREFIX "HIL KEYB: "
+#define HIL_GENERIC_NAME "HIL keyboard"
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define HIL_KBD_MAX_LENGTH 16
+
+#define HIL_KBD_SET1_UPBIT 0x01
+#define HIL_KBD_SET1_SHIFT 1
+static unsigned int hil_kbd_set1[HIL_KEYCODES_SET1_TBLSIZE] = 
+	{ HIL_KEYCODES_SET1 };
+
+#define HIL_KBD_SET2_UPBIT 0x01
+#define HIL_KBD_SET2_SHIFT 1
+/* Set2 is user defined */
+
+#define HIL_KBD_SET3_UPBIT 0x80
+#define HIL_KBD_SET3_SHIFT 0
+static unsigned int hil_kbd_set3[HIL_KEYCODES_SET3_TBLSIZE] =
+	{ HIL_KEYCODES_SET3 };
+
+static char hil_language[][16] = { HIL_LOCALE_MAP };
+
+struct hil_kbd {
+	struct input_dev dev;
+	struct serio *serio;
+
+	/* Input buffer and index for packets from HIL bus. */
+	hil_packet data[HIL_KBD_MAX_LENGTH];
+	int idx4; /* four counts per packet */
+
+	/* Raw device info records from HIL bus, see hil.h for fields. */
+	char	idd[HIL_KBD_MAX_LENGTH];	/* DID byte and IDD record */
+	char	rsc[HIL_KBD_MAX_LENGTH];	/* RSC record */
+	char	exd[HIL_KBD_MAX_LENGTH];	/* EXD record */
+	char	rnm[HIL_KBD_MAX_LENGTH + 1];	/* RNM record + NULL term. */
+
+	/* Something to sleep around with. */
+	struct semaphore sem;
+};
+
+/* Process a complete packet after transfer from the HIL */
+static void hil_kbd_process_record(struct hil_kbd *kbd)
+{
+	struct input_dev *dev = &kbd->dev;
+	hil_packet *data = kbd->data;
+	hil_packet p;
+	int idx, i, cnt;
+
+	idx = kbd->idx4/4;
+	p = data[idx - 1];
+
+	if ((p & ~HIL_CMDCT_POL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
+	if ((p & ~HIL_CMDCT_RPL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+
+	/* Not a poll response.  See if we are loading config records. */
+	switch (p & HIL_PKT_DATA_MASK) {
+	case HIL_CMD_IDD:
+		for (i = 0; i < idx; i++)
+			kbd->idd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH; i++)
+			kbd->idd[i] = 0;
+		break;
+	case HIL_CMD_RSC:
+		for (i = 0; i < idx; i++)
+			kbd->rsc[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH; i++)
+			kbd->rsc[i] = 0;
+		break;
+	case HIL_CMD_EXD:
+		for (i = 0; i < idx; i++)
+			kbd->exd[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH; i++)
+			kbd->exd[i] = 0;
+		break;
+	case HIL_CMD_RNM:
+		for (i = 0; i < idx; i++)
+			kbd->rnm[i] = kbd->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_KBD_MAX_LENGTH + 1; i++)
+			kbd->rnm[i] = '\0';
+		break;
+	default:
+		/* These occur when device isn't present */
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		/* Anything else we'd like to know about. */
+		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
+		break;
+	}
+	goto out;
+
+ report:
+	cnt = 1;
+	switch (kbd->data[0] & HIL_POL_CHARTYPE_MASK) {
+	case HIL_POL_CHARTYPE_NONE:
+		break;
+	case HIL_POL_CHARTYPE_ASCII:
+		while (cnt < idx - 1)
+			input_report_key(dev, kbd->data[cnt++] & 0x7f, 1);
+		break;
+	case HIL_POL_CHARTYPE_RSVD1:
+	case HIL_POL_CHARTYPE_RSVD2:
+	case HIL_POL_CHARTYPE_BINARY:
+		while (cnt < idx - 1)
+			input_report_key(dev, kbd->data[cnt++], 1);
+		break;
+	case HIL_POL_CHARTYPE_SET1:
+		while (cnt < idx - 1) {
+			unsigned int key;
+			int up;
+			key = kbd->data[cnt++];
+			up = key & HIL_KBD_SET1_UPBIT;
+			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+			key = hil_kbd_set1[key >> HIL_KBD_SET1_SHIFT];
+			if (key != KEY_RESERVED)
+				input_report_key(dev, key, !up);
+		}
+		break;
+	case HIL_POL_CHARTYPE_SET2:
+		while (cnt < idx - 1) {
+			unsigned int key;
+			int up;
+			key = kbd->data[cnt++];
+			up = key & HIL_KBD_SET2_UPBIT;
+			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+			key = key >> HIL_KBD_SET2_SHIFT;
+			if (key != KEY_RESERVED)
+				input_report_key(dev, key, !up);
+		}
+		break;
+	case HIL_POL_CHARTYPE_SET3:
+		while (cnt < idx - 1) {
+			unsigned int key;
+			int up;
+			key = kbd->data[cnt++];
+			up = key & HIL_KBD_SET3_UPBIT;
+			key &= (~HIL_KBD_SET1_UPBIT & 0xff);
+			key = hil_kbd_set3[key >> HIL_KBD_SET3_SHIFT];
+			if (key != KEY_RESERVED)
+				input_report_key(dev, key, !up);
+		}
+		break;
+	}
+ out:
+	kbd->idx4 = 0;
+	up(&kbd->sem);
+}
+
+static void hil_kbd_process_err(struct hil_kbd *kbd) {
+	printk(KERN_WARNING PREFIX "errored HIL packet\n");
+	kbd->idx4 = 0;
+	up(&kbd->sem);
+}
+
+static irqreturn_t hil_kbd_interrupt(struct serio *serio, 
+	      unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+	struct hil_kbd *kbd;
+	hil_packet packet;
+	int idx;
+
+	kbd = (struct hil_kbd *)serio->private;
+	if (kbd == NULL) {
+		BUG();
+		return IRQ_HANDLED;
+	}
+
+	if (kbd->idx4 >= (HIL_KBD_MAX_LENGTH * sizeof(hil_packet))) {
+		hil_kbd_process_err(kbd);
+		return IRQ_HANDLED;
+	}
+	idx = kbd->idx4/4;
+	if (!(kbd->idx4 % 4)) kbd->data[idx] = 0;
+	packet = kbd->data[idx];
+	packet |= ((hil_packet)data) << ((3 - (kbd->idx4 % 4)) * 8);
+	kbd->data[idx] = packet;
+
+	/* Records of N 4-byte hil_packets must terminate with a command. */
+	if ((++(kbd->idx4)) % 4) return IRQ_HANDLED;
+	if ((packet & 0xffff0000) != HIL_ERR_INT) {
+		hil_kbd_process_err(kbd);
+		return IRQ_HANDLED;
+	}
+	if (packet & HIL_PKT_CMD) hil_kbd_process_record(kbd);
+	return IRQ_HANDLED;
+}
+
+static void hil_kbd_disconnect(struct serio *serio)
+{
+	struct hil_kbd *kbd;
+
+	kbd = (struct hil_kbd *)serio->private;
+	if (kbd == NULL) {
+		BUG();
+		return;
+	}
+
+	input_unregister_device(&kbd->dev);
+	serio_close(serio);
+	kfree(kbd);
+}
+
+static void hil_kbd_connect(struct serio *serio, struct serio_driver *drv)
+{
+	struct hil_kbd	*kbd;
+	uint8_t		did, *idd;
+	int		i;
+	
+	if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
+
+	if (!(kbd = kmalloc(sizeof(struct hil_kbd), GFP_KERNEL))) return;
+	memset(kbd, 0, sizeof(struct hil_kbd));
+
+	if (serio_open(serio, drv)) goto bail0;
+
+	serio->private = kbd;
+	kbd->serio = serio;
+	kbd->dev.private = kbd;
+
+	init_MUTEX_LOCKED(&(kbd->sem));
+
+	/* Get device info.  MLC driver supplies devid/status/etc. */
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_IDD);
+	down(&(kbd->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RSC);
+	down(&(kbd->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RNM);
+	down(&(kbd->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_EXD);
+	down(&(kbd->sem));
+
+	up(&(kbd->sem));
+
+	did = kbd->idd[0];
+	idd = kbd->idd + 1;
+	switch (did & HIL_IDD_DID_TYPE_MASK) {
+	case HIL_IDD_DID_TYPE_KB_INTEGRAL:
+	case HIL_IDD_DID_TYPE_KB_ITF:
+	case HIL_IDD_DID_TYPE_KB_RSVD:
+	case HIL_IDD_DID_TYPE_CHAR:
+		printk(KERN_INFO PREFIX "HIL keyboard found (did = 0x%02x, lang = %s)\n",
+			did, hil_language[did & HIL_IDD_DID_TYPE_KB_LANG_MASK]);
+		break;
+	default:
+		goto bail1;
+	}
+
+	if(HIL_IDD_NUM_BUTTONS(idd) || HIL_IDD_NUM_AXES_PER_SET(*idd)) {
+		printk(KERN_INFO PREFIX "keyboards only, no combo devices supported.\n");
+		goto bail1;
+	}
+
+
+	kbd->dev.evbit[0]	= BIT(EV_KEY) | BIT(EV_REP);
+	kbd->dev.ledbit[0]	= BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+	kbd->dev.keycodemax	= HIL_KEYCODES_SET1_TBLSIZE;
+	kbd->dev.keycodesize	= sizeof(hil_kbd_set1[0]);
+	kbd->dev.keycode	= hil_kbd_set1;
+	kbd->dev.name		= strlen(kbd->rnm) ? kbd->rnm : HIL_GENERIC_NAME;
+	kbd->dev.phys		= "hpkbd/input0";	/* XXX */
+
+	kbd->dev.id.bustype	= BUS_HIL;
+	kbd->dev.id.vendor	= PCI_VENDOR_ID_HP;
+	kbd->dev.id.product	= 0x0001; /* TODO: get from kbd->rsc */
+	kbd->dev.id.version	= 0x0100; /* TODO: get from kbd->rsc */
+	kbd->dev.dev		= &serio->dev;
+
+	for (i = 0; i < 128; i++) {
+		set_bit(hil_kbd_set1[i], kbd->dev.keybit);
+		set_bit(hil_kbd_set3[i], kbd->dev.keybit);
+	}
+	clear_bit(0, kbd->dev.keybit);
+
+	input_register_device(&kbd->dev);
+	printk(KERN_INFO "input: %s, ID: %d\n",
+		kbd->dev.name, did);
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_EK1); /* Enable Keyswitch Autorepeat 1 */
+	down(&(kbd->sem));
+	up(&(kbd->sem));
+
+	return;
+ bail1:
+	serio_close(serio);
+ bail0:
+	kfree(kbd);
+}
+
+
+struct serio_driver hil_kbd_serio_drv = {
+	.driver		= {
+		.name	= "hil_kbd",
+	},
+	.description	= "HP HIL keyboard driver",
+	.connect 	= hil_kbd_connect,
+	.disconnect 	= hil_kbd_disconnect,
+	.interrupt 	= hil_kbd_interrupt
+};
+
+static int __init hil_kbd_init(void)
+{
+	serio_register_driver(&hil_kbd_serio_drv);
+        return 0;
+}
+                
+static void __exit hil_kbd_exit(void)
+{
+	serio_unregister_driver(&hil_kbd_serio_drv);
+}
+                        
+module_init(hil_kbd_init);
+module_exit(hil_kbd_exit);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/keyboard/hilkbd.c parisc-2.6-bk/drivers/input/keyboard/hilkbd.c
--- linux-2.6.10-rc1-bk13/drivers/input/keyboard/hilkbd.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/drivers/input/keyboard/hilkbd.c	Wed Nov  3 06:12:03 2004
@@ -0,0 +1,343 @@
+/*
+ *  linux/drivers/hil/hilkbd.c
+ *
+ *  Copyright (C) 1998 Philip Blundell <philb@gnu.org>
+ *  Copyright (C) 1999 Matthew Wilcox <willy@bofh.ai>
+ *  Copyright (C) 1999-2003 Helge Deller <deller@gmx.de>
+ *
+ *  Very basic HP Human Interface Loop (HIL) driver.
+ *  This driver handles the keyboard on HP300 (m68k) and on some 
+ *  HP700 (parisc) series machines.
+ *
+ * 
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License version 2.  See the file COPYING in the main directory of this
+ * archive for more details.
+ */
+
+#include <linux/pci_ids.h>
+#include <linux/ioport.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/errno.h>
+#include <linux/input.h>
+#include <linux/init.h>
+#include <linux/irq.h>
+#include <linux/hil.h>
+#include <linux/spinlock.h>
+
+
+MODULE_AUTHOR("Philip Blundell, Matthew Wilcox, Helge Deller");
+MODULE_DESCRIPTION("HIL keyboard driver (basic functionality)");
+MODULE_LICENSE("GPL v2");
+
+
+#if defined(CONFIG_PARISC)
+
+ #include <asm/io.h>
+ #include <asm/hardware.h>
+ #include <asm/parisc-device.h>
+ static unsigned long hil_base;	/* HPA for the HIL device */
+ static unsigned int hil_irq;
+ #define HILBASE		hil_base /* HPPA (parisc) port address */
+ #define HIL_DATA		0x800
+ #define HIL_CMD		0x801
+ #define HIL_IRQ		hil_irq
+ #define hil_readb(p)		gsc_readb(p)
+ #define hil_writeb(v,p)	gsc_writeb((v),(p))
+
+#elif defined(CONFIG_HP300)
+
+ #define HILBASE		0xf0428000 /* HP300 (m86k) port address */
+ #define HIL_DATA		0x1
+ #define HIL_CMD		0x3
+ #define HIL_IRQ		2
+ #define hil_readb(p)		readb(p)
+ #define hil_writeb(v,p)	writeb((v),(p))
+
+#else
+#error "HIL is not supported on this platform"
+#endif
+
+
+ 
+/* HIL helper functions */
+ 
+#define hil_busy()              (hil_readb(HILBASE + HIL_CMD) & HIL_BUSY)
+#define hil_data_available()    (hil_readb(HILBASE + HIL_CMD) & HIL_DATA_RDY)
+#define hil_status()            (hil_readb(HILBASE + HIL_CMD))
+#define hil_command(x)          do { hil_writeb((x), HILBASE + HIL_CMD); } while (0)
+#define hil_read_data()         (hil_readb(HILBASE + HIL_DATA))
+#define hil_write_data(x)       do { hil_writeb((x), HILBASE + HIL_DATA); } while (0)
+
+/* HIL constants */
+ 
+#define	HIL_BUSY		0x02
+#define	HIL_DATA_RDY		0x01
+
+#define	HIL_SETARD		0xA0		/* set auto-repeat delay */
+#define	HIL_SETARR		0xA2		/* set auto-repeat rate */
+#define	HIL_SETTONE		0xA3		/* set tone generator */
+#define	HIL_CNMT		0xB2		/* clear nmi */
+#define	HIL_INTON		0x5C		/* Turn on interrupts. */
+#define	HIL_INTOFF		0x5D		/* Turn off interrupts. */
+
+#define	HIL_READKBDSADR	 	0xF9
+#define	HIL_WRITEKBDSADR 	0xE9
+
+static unsigned int hphilkeyb_keycode[HIL_KEYCODES_SET1_TBLSIZE] = 
+	{ HIL_KEYCODES_SET1 };
+
+/* HIL structure */
+static struct {
+	struct input_dev dev;
+
+	unsigned int curdev;
+	
+	unsigned char s;
+	unsigned char c;
+	int valid;
+	
+	unsigned char data[16];
+	unsigned int ptr;
+	spinlock_t lock;
+
+	void *dev_id;	/* native bus device */
+} hil_dev;
+
+
+static void poll_finished(void)
+{
+	int down;
+	int key;
+	unsigned char scode;
+	
+	switch (hil_dev.data[0]) {
+	case 0x40:
+		down = (hil_dev.data[1] & 1) == 0;
+		scode = hil_dev.data[1] >> 1;
+		key = hphilkeyb_keycode[scode];
+		input_report_key(&hil_dev.dev, key, down);
+		break;
+	}
+	hil_dev.curdev = 0;
+}
+
+static inline void handle_status(unsigned char s, unsigned char c)
+{
+	if (c & 0x8) {
+		/* End of block */
+		if (c & 0x10)
+			poll_finished();
+	} else {
+		if (c & 0x10) {
+			if (hil_dev.curdev)
+				poll_finished();  /* just in case */
+			hil_dev.curdev = c & 7;
+			hil_dev.ptr = 0;
+		}
+	}
+}
+
+static inline void handle_data(unsigned char s, unsigned char c)
+{
+	if (hil_dev.curdev) {
+		hil_dev.data[hil_dev.ptr++] = c;
+		hil_dev.ptr &= 15;
+	}
+}
+
+
+/* 
+ * Handle HIL interrupts.
+ */
+static irqreturn_t hil_interrupt(int irq, void *handle, struct pt_regs *regs)
+{
+	unsigned char s, c;
+	
+	s = hil_status();
+	c = hil_read_data();
+
+	switch (s >> 4) {
+	case 0x5:
+		handle_status(s, c);
+		break;
+	case 0x6:
+		handle_data(s, c);
+		break;
+	case 0x4:
+		hil_dev.s = s;
+		hil_dev.c = c;
+		mb();
+		hil_dev.valid = 1;
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+/*
+ * Send a command to the HIL
+ */
+
+static void hil_do(unsigned char cmd, unsigned char *data, unsigned int len)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hil_dev.lock, flags);
+	while (hil_busy())
+		/* wait */;
+	hil_command(cmd);
+	while (len--) {
+		while (hil_busy())
+			/* wait */;
+		hil_write_data(*(data++));
+	}
+	spin_unlock_irqrestore(&hil_dev.lock, flags);
+}
+
+
+/*
+ * Initialise HIL. 
+ */
+
+static int __init
+hil_keyb_init(void)
+{
+	unsigned char c;
+	unsigned int i, kbid;
+	wait_queue_head_t hil_wait;
+
+	if (hil_dev.dev.id.bustype) {
+		return -ENODEV; /* already initialized */
+	}
+	
+#if defined(CONFIG_HP300)
+	if (!hwreg_present((void *)(HILBASE + HIL_DATA)))
+		return -ENODEV;
+	
+	request_region(HILBASE+HIL_DATA, 2, "hil");
+#endif
+	
+	request_irq(HIL_IRQ, hil_interrupt, 0, "hil", hil_dev.dev_id);
+
+	/* Turn on interrupts */
+	hil_do(HIL_INTON, NULL, 0);
+
+	/* Look for keyboards */
+	hil_dev.valid = 0;	/* clear any pending data */
+	hil_do(HIL_READKBDSADR, NULL, 0);
+
+	init_waitqueue_head(&hil_wait);
+	wait_event_interruptible_timeout(hil_wait, hil_dev.valid, 3*HZ);
+	if (!hil_dev.valid) {
+		printk(KERN_WARNING "HIL: timed out, assuming no keyboard present.\n");
+	}
+
+	c = hil_dev.c; 
+	hil_dev.valid = 0;
+	if (c == 0) {
+		kbid = -1;
+		printk(KERN_WARNING "HIL: no keyboard present.\n");
+	} else {
+		kbid = ffz(~c);
+		/* printk(KERN_INFO "HIL: keyboard found at id %d\n", kbid); */
+	}
+
+	/* set it to raw mode */
+	c = 0;
+	hil_do(HIL_WRITEKBDSADR, &c, 1);
+	
+	init_input_dev(&hil_dev.dev);
+
+	for (i = 0; i < HIL_KEYCODES_SET1_TBLSIZE; i++)
+		if (hphilkeyb_keycode[i] != KEY_RESERVED)
+			set_bit(hphilkeyb_keycode[i], hil_dev.dev.keybit);
+
+	hil_dev.dev.evbit[0]    = BIT(EV_KEY) | BIT(EV_REP);
+	hil_dev.dev.ledbit[0]   = BIT(LED_NUML) | BIT(LED_CAPSL) | BIT(LED_SCROLLL);
+	hil_dev.dev.keycodemax  = HIL_KEYCODES_SET1_TBLSIZE;
+        hil_dev.dev.keycodesize = sizeof(hphilkeyb_keycode[0]);
+	hil_dev.dev.keycode     = hphilkeyb_keycode;
+	hil_dev.dev.name 	= "HIL keyboard";
+	hil_dev.dev.phys 	= "hpkbd/input0";
+
+	hil_dev.dev.id.bustype	= BUS_HIL;
+	hil_dev.dev.id.vendor	= PCI_VENDOR_ID_HP;
+	hil_dev.dev.id.product	= 0x0001;
+	hil_dev.dev.id.version	= 0x0010;
+
+	input_register_device(&hil_dev.dev);
+	printk(KERN_INFO "input: %s, ID %d at 0x%08lx (irq %d) found and attached\n",
+		hil_dev.dev.name, kbid, HILBASE, HIL_IRQ);
+
+	return 0;
+}
+
+#if defined(CONFIG_PARISC)
+static int __init
+hil_init_chip(struct parisc_device *dev)
+{
+	if (!dev->irq) {
+		printk(KERN_WARNING "HIL: IRQ not found for HIL bus at 0x%08lx\n", dev->hpa);
+		return -ENODEV;
+	}
+
+	hil_base = dev->hpa;
+	hil_irq  = dev->irq;
+	hil_dev.dev_id = dev;
+	
+	printk(KERN_INFO "Found HIL bus at 0x%08lx, IRQ %d\n", hil_base, hil_irq);
+
+	return hil_keyb_init();
+}
+
+static struct parisc_device_id hil_tbl[] = {
+	{ HPHW_FIO, HVERSION_REV_ANY_ID, HVERSION_ANY_ID, 0x00073 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, hil_tbl);
+
+static struct parisc_driver hil_driver = {
+	.name =		"HIL",
+	.id_table =	hil_tbl,
+	.probe =	hil_init_chip,
+};
+#endif /* CONFIG_PARISC */
+
+
+
+
+
+static int __init hil_init(void)
+{
+#if defined(CONFIG_PARISC)
+	return register_parisc_driver(&hil_driver);
+#else
+	return hil_keyb_init();
+#endif
+}
+
+
+static void __exit hil_exit(void)
+{
+	if (HIL_IRQ) {
+		disable_irq(HIL_IRQ);
+		free_irq(HIL_IRQ, hil_dev.dev_id);
+	}
+
+	/* Turn off interrupts */
+	hil_do(HIL_INTOFF, NULL, 0);
+
+	input_unregister_device(&hil_dev.dev);
+
+#if defined(CONFIG_PARISC)
+	unregister_parisc_driver(&hil_driver);
+#else
+	release_region(HILBASE+HIL_DATA, 2);
+#endif
+}
+
+module_init(hil_init);
+module_exit(hil_exit);
+
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/keyboard/hpps2atkbd.h parisc-2.6-bk/drivers/input/keyboard/hpps2atkbd.h
--- linux-2.6.10-rc1-bk13/drivers/input/keyboard/hpps2atkbd.h	Fri Oct 22 15:38:16 2004
+++ parisc-2.6-bk/drivers/input/keyboard/hpps2atkbd.h	Wed Nov  3 06:19:01 2004
@@ -14,10 +14,8 @@
  */
 
 
-/* undefine if you have a RDI PRECISIONBOOK */
-#define STANDARD_KEYBOARD
-
-#if defined(STANDARD_KEYBOARD)
+/* Is the keyboard an RDI PrecisionBook? */
+#ifndef CONFIG_KEYBOARD_ATKBD_RDI_KEYCODES
 # define CONFLICT(x,y) x
 #else
 # define CONFLICT(x,y) y
@@ -50,10 +48,10 @@
 /* 60 */  KEY_DOWN,     C_61,          KEY_PAUSE,     KEY_UP,        KEY_DELETE,    KEY_END,      KEY_BACKSPACE, KEY_INSERT,
 /* 68 */  KEY_RESERVED, KEY_KP1,       KEY_RIGHT,     KEY_KP4,       KEY_KP7,       KEY_PAGEDOWN, KEY_HOME,      KEY_PAGEUP,
 /* 70 */  KEY_KP0,      KEY_KPDOT,     KEY_KP2,       KEY_KP5,       KEY_KP6,       KEY_KP8,      KEY_ESC,       KEY_NUMLOCK,
-/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_103RD,
+/* 78 */  KEY_F11,      KEY_KPPLUS,    KEY_KP3,       KEY_KPMINUS,   KEY_KPASTERISK,KEY_KP9,      KEY_SCROLLLOCK,KEY_102ND,
 /* 80 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
 /* 88 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
-/* 90 */  KEY_RESERVED, KEY_RIGHTALT,  KEY_SYSRQ,     KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
+/* 90 */  KEY_RESERVED, KEY_RIGHTALT,  255,           KEY_RESERVED,  KEY_RIGHTCTRL, KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
 /* 98 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_CAPSLOCK, KEY_RESERVED,  KEY_LEFTMETA,
 /* a0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RIGHTMETA,
 /* a8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_COMPOSE,
@@ -103,7 +101,6 @@
 /* f0 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,
 /* f8 */  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED,  KEY_RESERVED, KEY_RESERVED,  KEY_RESERVED
 
-#undef STANDARD_KEYBOARD
 #undef CONFLICT
 #undef C_07
 #undef C_11
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/misc/Kconfig parisc-2.6-bk/drivers/input/misc/Kconfig
--- linux-2.6.10-rc1-bk13/drivers/input/misc/Kconfig	Fri Oct 22 15:39:07 2004
+++ parisc-2.6-bk/drivers/input/misc/Kconfig	Wed Nov  3 06:19:01 2004
@@ -50,3 +50,11 @@ config INPUT_UINPUT
 	  To compile this driver as a module, choose M here: the
 	  module will be called uinput.
 
+config HP_SDC_RTC
+	tristate "HP SDC Real Time Clock"
+	depends on INPUT && INPUT_MISC && GSC
+	select HP_SDC
+	help
+	  Say Y here if you want to support the built-in real time clock
+	  of the HP SDC controller.
+
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/misc/Makefile parisc-2.6-bk/drivers/input/misc/Makefile
--- linux-2.6.10-rc1-bk13/drivers/input/misc/Makefile	Fri Oct 22 15:39:43 2004
+++ parisc-2.6-bk/drivers/input/misc/Makefile	Wed Nov  3 06:19:01 2004
@@ -9,3 +9,4 @@ obj-$(CONFIG_INPUT_PCSPKR)		+= pcspkr.o
 obj-$(CONFIG_INPUT_M68K_BEEP)		+= m68kspkr.o
 obj-$(CONFIG_INPUT_98SPKR)		+= 98spkr.o
 obj-$(CONFIG_INPUT_UINPUT)		+= uinput.o
+obj-$(CONFIG_HP_SDC_RTC)		+= hp_sdc_rtc.o
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/misc/hp_sdc_rtc.c parisc-2.6-bk/drivers/input/misc/hp_sdc_rtc.c
--- linux-2.6.10-rc1-bk13/drivers/input/misc/hp_sdc_rtc.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/drivers/input/misc/hp_sdc_rtc.c	Wed Nov  3 06:12:03 2004
@@ -0,0 +1,724 @@
+/*
+ * HP i8042 SDC + MSM-58321 BBRTC driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ * efirtc.c by Stephane Eranian/Hewlett Packard
+ *
+ */
+
+#include <linux/hp_sdc.h>
+#include <linux/errno.h>
+#include <linux/types.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/time.h>
+#include <linux/miscdevice.h>
+#include <linux/proc_fs.h>
+#include <linux/poll.h>
+#include <linux/rtc.h>
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HP i8042 SDC + MSM-58321 RTC Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+#define RTC_VERSION "1.10d"
+
+static unsigned long epoch = 2000;
+
+static struct semaphore i8042tregs;
+
+static hp_sdc_irqhook hp_sdc_rtc_isr;
+
+static struct fasync_struct *hp_sdc_rtc_async_queue;
+
+static DECLARE_WAIT_QUEUE_HEAD(hp_sdc_rtc_wait);
+
+static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin);
+
+static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
+			       size_t count, loff_t *ppos);
+
+static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file,
+			    unsigned int cmd, unsigned long arg);
+
+static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait);
+
+static int hp_sdc_rtc_open(struct inode *inode, struct file *file);
+static int hp_sdc_rtc_release(struct inode *inode, struct file *file);
+static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on);
+
+static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
+				int count, int *eof, void *data);
+
+static void hp_sdc_rtc_isr (int irq, void *dev_id, 
+			    uint8_t status, uint8_t data) 
+{
+	return;
+}
+
+static int hp_sdc_rtc_do_read_bbrtc (struct rtc_time *rtctm)
+{
+	struct semaphore tsem;
+	hp_sdc_transaction t;
+	uint8_t tseq[91];
+	int i;
+	
+	i = 0;
+	while (i < 91) {
+		tseq[i++] = HP_SDC_ACT_DATAREG |
+			HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN;
+		tseq[i++] = 0x01;			/* write i8042[0x70] */
+	  	tseq[i]   = i / 7;			/* BBRTC reg address */
+		i++;
+		tseq[i++] = HP_SDC_CMD_DO_RTCR;		/* Trigger command   */
+		tseq[i++] = 2;		/* expect 1 stat/dat pair back.   */
+		i++; i++;               /* buffer for stat/dat pair       */
+	}
+	tseq[84] |= HP_SDC_ACT_SEMAPHORE;
+	t.endidx =		91;
+	t.seq =			tseq;
+	t.act.semaphore =	&tsem;
+	init_MUTEX_LOCKED(&tsem);
+	
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	
+	down_interruptible(&tsem);  /* Put ourselves to sleep for results. */
+	
+	/* Check for nonpresence of BBRTC */
+	if (!((tseq[83] | tseq[90] | tseq[69] | tseq[76] |
+	       tseq[55] | tseq[62] | tseq[34] | tseq[41] |
+	       tseq[20] | tseq[27] | tseq[6]  | tseq[13]) & 0x0f))
+		return -1;
+
+	memset(rtctm, 0, sizeof(struct rtc_time));
+	rtctm->tm_year = (tseq[83] & 0x0f) + (tseq[90] & 0x0f) * 10;
+	rtctm->tm_mon  = (tseq[69] & 0x0f) + (tseq[76] & 0x0f) * 10;
+	rtctm->tm_mday = (tseq[55] & 0x0f) + (tseq[62] & 0x0f) * 10;
+	rtctm->tm_wday = (tseq[48] & 0x0f);
+	rtctm->tm_hour = (tseq[34] & 0x0f) + (tseq[41] & 0x0f) * 10;
+	rtctm->tm_min  = (tseq[20] & 0x0f) + (tseq[27] & 0x0f) * 10;
+	rtctm->tm_sec  = (tseq[6]  & 0x0f) + (tseq[13] & 0x0f) * 10;
+	
+	return 0;
+}
+
+static int hp_sdc_rtc_read_bbrtc (struct rtc_time *rtctm)
+{
+	struct rtc_time tm, tm_last;
+	int i = 0;
+
+	/* MSM-58321 has no read latch, so must read twice and compare. */
+
+	if (hp_sdc_rtc_do_read_bbrtc(&tm_last)) return -1;
+	if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
+
+	while (memcmp(&tm, &tm_last, sizeof(struct rtc_time))) {
+		if (i++ > 4) return -1;
+		memcpy(&tm_last, &tm, sizeof(struct rtc_time));
+		if (hp_sdc_rtc_do_read_bbrtc(&tm)) return -1;
+	}
+
+	memcpy(rtctm, &tm, sizeof(struct rtc_time));
+
+	return 0;
+}
+
+
+static int64_t hp_sdc_rtc_read_i8042timer (uint8_t loadcmd, int numreg)
+{
+	hp_sdc_transaction t;
+	uint8_t tseq[26] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN,
+		0,
+		HP_SDC_CMD_READ_T1, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T2, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T3, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T4, 2, 0, 0,
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN, 
+		HP_SDC_CMD_READ_T5, 2, 0, 0
+	};
+
+	t.endidx = numreg * 5;
+
+	tseq[1] = loadcmd;
+	tseq[t.endidx - 4] |= HP_SDC_ACT_SEMAPHORE; /* numreg assumed > 1 */
+
+	t.seq =			tseq;
+	t.act.semaphore =	&i8042tregs;
+
+	down_interruptible(&i8042tregs);  /* Sleep if output regs in use. */
+
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	
+	down_interruptible(&i8042tregs);  /* Sleep until results come back. */
+	up(&i8042tregs);
+
+	return (tseq[5] | 
+		((uint64_t)(tseq[10]) << 8)  | ((uint64_t)(tseq[15]) << 16) |
+		((uint64_t)(tseq[20]) << 24) | ((uint64_t)(tseq[25]) << 32));
+}
+
+
+/* Read the i8042 real-time clock */
+static inline int hp_sdc_rtc_read_rt(struct timeval *res) {
+	int64_t raw;
+	uint32_t tenms; 
+	unsigned int days;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_RT, 5);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+	days  = (unsigned int)(raw >> 24) & 0xffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec =  (time_t)(tenms / 100) + days * 86400;
+
+	return 0;
+}
+
+
+/* Read the i8042 fast handshake timer */
+static inline int hp_sdc_rtc_read_fhs(struct timeval *res) {
+	uint64_t raw;
+	unsigned int tenms;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_FHS, 2);
+	if (raw < 0) return -1;
+
+	tenms = (unsigned int)raw & 0xffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Read the i8042 match timer (a.k.a. alarm) */
+static inline int hp_sdc_rtc_read_mt(struct timeval *res) {
+	int64_t raw;	
+	uint32_t tenms; 
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_MT, 3);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Read the i8042 delay timer */
+static inline int hp_sdc_rtc_read_dt(struct timeval *res) {
+	int64_t raw;
+	uint32_t tenms;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_DT, 3);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Read the i8042 cycle timer (a.k.a. periodic) */
+static inline int hp_sdc_rtc_read_ct(struct timeval *res) {
+	int64_t raw;
+	uint32_t tenms;
+
+	raw = hp_sdc_rtc_read_i8042timer(HP_SDC_CMD_LOAD_CT, 3);
+	if (raw < 0) return -1;
+
+	tenms = (uint32_t)raw & 0xffffff;
+
+	res->tv_usec = (suseconds_t)(tenms % 100) * 10000;
+	res->tv_sec  = (time_t)(tenms / 100);
+
+	return 0;
+}
+
+
+/* Set the i8042 real-time clock */
+static int hp_sdc_rtc_set_rt (struct timeval *setto)
+{
+	uint32_t tenms;
+	unsigned int days;
+	hp_sdc_transaction t;
+	uint8_t tseq[11] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		HP_SDC_CMD_SET_RTMS, 3, 0, 0, 0,
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		HP_SDC_CMD_SET_RTD, 2, 0, 0 
+	};
+
+	t.endidx = 10;
+
+	if (0xffff < setto->tv_sec / 86400) return -1;
+	days = setto->tv_sec / 86400;
+	if (0xffff < setto->tv_usec / 1000000 / 86400) return -1;
+	days += ((setto->tv_sec % 86400) + setto->tv_usec / 1000000) / 86400;
+	if (days > 0xffff) return -1;
+
+	if (0xffffff < setto->tv_sec) return -1;
+	tenms  = setto->tv_sec * 100;
+	if (0xffffff < setto->tv_usec / 10000) return -1;
+	tenms += setto->tv_usec / 10000;
+	if (tenms > 0xffffff) return -1;
+
+	tseq[3] = (uint8_t)(tenms & 0xff);
+	tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
+	tseq[5] = (uint8_t)((tenms >> 16) & 0xff);
+
+	tseq[9] = (uint8_t)(days & 0xff);
+	tseq[10] = (uint8_t)((days >> 8) & 0xff);
+
+	t.seq =	tseq;
+
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	return 0;
+}
+
+/* Set the i8042 fast handshake timer */
+static int hp_sdc_rtc_set_fhs (struct timeval *setto)
+{
+	uint32_t tenms;
+	hp_sdc_transaction t;
+	uint8_t tseq[5] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		HP_SDC_CMD_SET_FHS, 2, 0, 0
+	};
+
+	t.endidx = 4;
+
+	if (0xffff < setto->tv_sec) return -1;
+	tenms  = setto->tv_sec * 100;
+	if (0xffff < setto->tv_usec / 10000) return -1;
+	tenms += setto->tv_usec / 10000;
+	if (tenms > 0xffff) return -1;
+
+	tseq[3] = (uint8_t)(tenms & 0xff);
+	tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
+
+	t.seq =	tseq;
+
+	if (hp_sdc_enqueue_transaction(&t)) return -1;
+	return 0;
+}
+
+
+/* Set the i8042 match timer (a.k.a. alarm) */
+#define hp_sdc_rtc_set_mt (setto) \
+	hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_MT)
+
+/* Set the i8042 delay timer */
+#define hp_sdc_rtc_set_dt (setto) \
+	hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_DT)
+
+/* Set the i8042 cycle timer (a.k.a. periodic) */
+#define hp_sdc_rtc_set_ct (setto) \
+	hp_sdc_rtc_set_i8042timer(setto, HP_SDC_CMD_SET_CT)
+
+/* Set one of the i8042 3-byte wide timers */
+static int hp_sdc_rtc_set_i8042timer (struct timeval *setto, uint8_t setcmd)
+{
+	uint32_t tenms;
+	hp_sdc_transaction t;
+	uint8_t tseq[6] = {
+		HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT,
+		0, 3, 0, 0, 0
+	};
+
+	t.endidx = 6;
+
+	if (0xffffff < setto->tv_sec) return -1;
+	tenms  = setto->tv_sec * 100;
+	if (0xffffff < setto->tv_usec / 10000) return -1;
+	tenms += setto->tv_usec / 10000;
+	if (tenms > 0xffffff) return -1;
+
+	tseq[1] = setcmd;
+	tseq[3] = (uint8_t)(tenms & 0xff);
+	tseq[4] = (uint8_t)((tenms >> 8)  & 0xff);
+	tseq[5] = (uint8_t)((tenms >> 16)  & 0xff);
+
+	t.seq =			tseq;
+
+	if (hp_sdc_enqueue_transaction(&t)) { 
+		return -1;
+	}
+	return 0;
+}
+
+static loff_t hp_sdc_rtc_llseek(struct file *file, loff_t offset, int origin)
+{
+        return -ESPIPE;
+}
+
+static ssize_t hp_sdc_rtc_read(struct file *file, char *buf,
+			       size_t count, loff_t *ppos) {
+	ssize_t retval;
+
+        if (count < sizeof(unsigned long))
+                return -EINVAL;
+
+	retval = put_user(68, (unsigned long *)buf);
+	return retval;
+}
+
+static unsigned int hp_sdc_rtc_poll(struct file *file, poll_table *wait)
+{
+        unsigned long l;
+
+	l = 0;
+        if (l != 0)
+                return POLLIN | POLLRDNORM;
+        return 0;
+}
+
+static int hp_sdc_rtc_open(struct inode *inode, struct file *file)
+{
+        return 0;
+}
+
+static int hp_sdc_rtc_release(struct inode *inode, struct file *file)
+{
+	/* Turn off interrupts? */
+
+        if (file->f_flags & FASYNC) {
+                hp_sdc_rtc_fasync (-1, file, 0);
+        }
+
+        return 0;
+}
+
+static int hp_sdc_rtc_fasync (int fd, struct file *filp, int on)
+{
+        return fasync_helper (fd, filp, on, &hp_sdc_rtc_async_queue);
+}
+
+static int hp_sdc_rtc_proc_output (char *buf)
+{
+#define YN(bit) ("no")
+#define NY(bit) ("yes")
+        char *p;
+        struct rtc_time tm;
+	struct timeval tv;
+
+	memset(&tm, 0, sizeof(struct rtc_time));
+
+	p = buf;
+
+	if (hp_sdc_rtc_read_bbrtc(&tm)) {
+		p += sprintf(p, "BBRTC\t\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p,
+			     "rtc_time\t: %02d:%02d:%02d\n"
+			     "rtc_date\t: %04d-%02d-%02d\n"
+			     "rtc_epoch\t: %04lu\n",
+			     tm.tm_hour, tm.tm_min, tm.tm_sec,
+			     tm.tm_year + 1900, tm.tm_mon + 1, 
+			     tm.tm_mday, epoch);
+	}
+
+	if (hp_sdc_rtc_read_rt(&tv)) {
+		p += sprintf(p, "i8042 rtc\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "i8042 rtc\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_fhs(&tv)) {
+		p += sprintf(p, "handshake\t: READ FAILED!\n");
+	} else {
+        	p += sprintf(p, "handshake\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_mt(&tv)) {
+		p += sprintf(p, "alarm\t\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "alarm\t\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_dt(&tv)) {
+		p += sprintf(p, "delay\t\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "delay\t\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+	if (hp_sdc_rtc_read_ct(&tv)) {
+		p += sprintf(p, "periodic\t: READ FAILED!\n");
+	} else {
+		p += sprintf(p, "periodic\t: %ld.%02d seconds\n", 
+			     tv.tv_sec, tv.tv_usec/1000);
+	}
+
+        p += sprintf(p,
+                     "DST_enable\t: %s\n"
+                     "BCD\t\t: %s\n"
+                     "24hr\t\t: %s\n"
+                     "square_wave\t: %s\n"
+                     "alarm_IRQ\t: %s\n"
+                     "update_IRQ\t: %s\n"
+                     "periodic_IRQ\t: %s\n"
+		     "periodic_freq\t: %ld\n"
+                     "batt_status\t: %s\n",
+                     YN(RTC_DST_EN),
+                     NY(RTC_DM_BINARY),
+                     YN(RTC_24H),
+                     YN(RTC_SQWE),
+                     YN(RTC_AIE),
+                     YN(RTC_UIE),
+                     YN(RTC_PIE),
+                     1UL,
+                     1 ? "okay" : "dead");
+
+        return  p - buf;
+#undef YN
+#undef NY
+}
+
+static int hp_sdc_rtc_read_proc(char *page, char **start, off_t off,
+                         int count, int *eof, void *data)
+{
+	int len = hp_sdc_rtc_proc_output (page);
+        if (len <= off+count) *eof = 1;
+        *start = page + off;
+        len -= off;
+        if (len>count) len = count;
+        if (len<0) len = 0;
+        return len;
+}
+
+static int hp_sdc_rtc_ioctl(struct inode *inode, struct file *file, 
+			    unsigned int cmd, unsigned long arg)
+{
+#if 1
+	return -EINVAL;
+#else
+	
+        struct rtc_time wtime; 
+	struct timeval ttime;
+	int use_wtime = 0;
+
+	/* This needs major work. */
+
+        switch (cmd) {
+
+        case RTC_AIE_OFF:       /* Mask alarm int. enab. bit    */
+        case RTC_AIE_ON:        /* Allow alarm interrupts.      */
+	case RTC_PIE_OFF:       /* Mask periodic int. enab. bit */
+        case RTC_PIE_ON:        /* Allow periodic ints          */
+        case RTC_UIE_ON:        /* Allow ints for RTC updates.  */
+        case RTC_UIE_OFF:       /* Allow ints for RTC updates.  */
+        {
+		/* We cannot mask individual user timers and we
+		   cannot tell them apart when they occur, so it 
+		   would be disingenuous to succeed these IOCTLs */
+		return -EINVAL;
+        }
+        case RTC_ALM_READ:      /* Read the present alarm time */
+        {
+		if (hp_sdc_rtc_read_mt(&ttime)) return -EFAULT;
+		if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
+
+		wtime.tm_hour = ttime.tv_sec / 3600;  ttime.tv_sec %= 3600;
+		wtime.tm_min  = ttime.tv_sec / 60;    ttime.tv_sec %= 60;
+		wtime.tm_sec  = ttime.tv_sec;
+                
+		break;
+        }
+        case RTC_IRQP_READ:     /* Read the periodic IRQ rate.  */
+        {
+                return put_user(hp_sdc_rtc_freq, (unsigned long *)arg);
+        }
+        case RTC_IRQP_SET:      /* Set periodic IRQ rate.       */
+        {
+                /* 
+                 * The max we can do is 100Hz.
+		 */
+
+                if ((arg < 1) || (arg > 100)) return -EINVAL;
+		ttime.tv_sec = 0;
+		ttime.tv_usec = 1000000 / arg;
+		if (hp_sdc_rtc_set_ct(&ttime)) return -EFAULT;
+		hp_sdc_rtc_freq = arg;
+                return 0;
+        }
+        case RTC_ALM_SET:       /* Store a time into the alarm */
+        {
+                /*
+                 * This expects a struct hp_sdc_rtc_time. Writing 0xff means
+                 * "don't care" or "match all" for PC timers.  The HP SDC
+		 * does not support that perk, but it could be emulated fairly
+		 * easily.  Only the tm_hour, tm_min and tm_sec are used.
+		 * We could do it with 10ms accuracy with the HP SDC, if the 
+		 * rtc interface left us a way to do that.
+                 */
+                struct hp_sdc_rtc_time alm_tm;
+
+                if (copy_from_user(&alm_tm, (struct hp_sdc_rtc_time*)arg,
+                                   sizeof(struct hp_sdc_rtc_time)))
+                       return -EFAULT;
+
+                if (alm_tm.tm_hour > 23) return -EINVAL;
+		if (alm_tm.tm_min  > 59) return -EINVAL;
+		if (alm_tm.tm_sec  > 59) return -EINVAL;  
+
+		ttime.sec = alm_tm.tm_hour * 3600 + 
+		  alm_tm.tm_min * 60 + alm_tm.tm_sec;
+		ttime.usec = 0;
+		if (hp_sdc_rtc_set_mt(&ttime)) return -EFAULT;
+                return 0;
+        }
+        case RTC_RD_TIME:       /* Read the time/date from RTC  */
+        {
+		if (hp_sdc_rtc_read_bbrtc(&wtime)) return -EFAULT;
+                break;
+        }
+        case RTC_SET_TIME:      /* Set the RTC */
+        {
+                struct rtc_time hp_sdc_rtc_tm;
+                unsigned char mon, day, hrs, min, sec, leap_yr;
+                unsigned int yrs;
+
+                if (!capable(CAP_SYS_TIME))
+                        return -EACCES;
+		if (copy_from_user(&hp_sdc_rtc_tm, (struct rtc_time *)arg,
+                                   sizeof(struct rtc_time)))
+                        return -EFAULT;
+
+                yrs = hp_sdc_rtc_tm.tm_year + 1900;
+                mon = hp_sdc_rtc_tm.tm_mon + 1;   /* tm_mon starts at zero */
+                day = hp_sdc_rtc_tm.tm_mday;
+                hrs = hp_sdc_rtc_tm.tm_hour;
+                min = hp_sdc_rtc_tm.tm_min;
+                sec = hp_sdc_rtc_tm.tm_sec;
+
+                if (yrs < 1970)
+                        return -EINVAL;
+
+                leap_yr = ((!(yrs % 4) && (yrs % 100)) || !(yrs % 400));
+
+                if ((mon > 12) || (day == 0))
+                        return -EINVAL;
+                if (day > (days_in_mo[mon] + ((mon == 2) && leap_yr)))
+                        return -EINVAL;
+		if ((hrs >= 24) || (min >= 60) || (sec >= 60))
+                        return -EINVAL;
+
+                if ((yrs -= eH) > 255)    /* They are unsigned */
+                        return -EINVAL;
+
+
+                return 0;
+        }
+        case RTC_EPOCH_READ:    /* Read the epoch.      */
+        {
+                return put_user (epoch, (unsigned long *)arg);
+        }
+        case RTC_EPOCH_SET:     /* Set the epoch.       */
+        {
+                /* 
+                 * There were no RTC clocks before 1900.
+                 */
+                if (arg < 1900)
+		  return -EINVAL;
+		if (!capable(CAP_SYS_TIME))
+		  return -EACCES;
+		
+                epoch = arg;
+                return 0;
+        }
+        default:
+                return -EINVAL;
+        }
+        return copy_to_user((void *)arg, &wtime, sizeof wtime) ? -EFAULT : 0;
+#endif
+}
+
+static struct file_operations hp_sdc_rtc_fops = {
+        .owner =	THIS_MODULE,
+        .llseek =	hp_sdc_rtc_llseek,
+        .read =		hp_sdc_rtc_read,
+        .poll =		hp_sdc_rtc_poll,
+        .ioctl =	hp_sdc_rtc_ioctl,
+        .open =		hp_sdc_rtc_open,
+        .release =	hp_sdc_rtc_release,
+        .fasync =	hp_sdc_rtc_fasync,
+};
+
+static struct miscdevice hp_sdc_rtc_dev = {
+        .minor =	RTC_MINOR,
+        .name =		"rtc_HIL",
+        .fops =		&hp_sdc_rtc_fops
+};
+
+static int __init hp_sdc_rtc_init(void)
+{
+	int ret;
+
+	init_MUTEX(&i8042tregs);
+
+	if ((ret = hp_sdc_request_timer_irq(&hp_sdc_rtc_isr)))
+		return ret;
+	misc_register(&hp_sdc_rtc_dev);
+        create_proc_read_entry ("driver/rtc", 0, 0, 
+				hp_sdc_rtc_read_proc, NULL);
+
+	printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support loaded "
+			 "(RTC v " RTC_VERSION ")\n");
+
+	return 0;
+}
+
+static void __exit hp_sdc_rtc_exit(void)
+{
+	remove_proc_entry ("driver/rtc", NULL);
+        misc_deregister(&hp_sdc_rtc_dev);
+	hp_sdc_release_timer_irq(hp_sdc_rtc_isr);
+        printk(KERN_INFO "HP i8042 SDC + MSM-58321 RTC support unloaded\n");
+}
+
+module_init(hp_sdc_rtc_init);
+module_exit(hp_sdc_rtc_exit);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/mouse/Kconfig parisc-2.6-bk/drivers/input/mouse/Kconfig
--- linux-2.6.10-rc1-bk13/drivers/input/mouse/Kconfig	Fri Oct 22 15:40:06 2004
+++ parisc-2.6-bk/drivers/input/mouse/Kconfig	Wed Nov  3 06:19:01 2004
@@ -128,3 +128,10 @@ config MOUSE_VSXXXAA
 	  described in the source file). This driver also works with the
 	  digitizer (VSXXX-AB) DEC produced.
 
+config MOUSE_HIL
+	tristate "HIL pointers (mice etc)."
+	depends on GSC && INPUT_MOUSE
+	select HP_SDC
+	select HIL_MLC
+	help
+	  Say Y here to support HIL pointers.
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/mouse/Makefile parisc-2.6-bk/drivers/input/mouse/Makefile
--- linux-2.6.10-rc1-bk13/drivers/input/mouse/Makefile	Fri Oct 22 15:38:39 2004
+++ parisc-2.6-bk/drivers/input/mouse/Makefile	Wed Nov  3 06:19:01 2004
@@ -12,6 +12,7 @@ obj-$(CONFIG_MOUSE_MAPLE)	+= maplemouse.
 obj-$(CONFIG_MOUSE_PC110PAD)	+= pc110pad.o
 obj-$(CONFIG_MOUSE_PS2)		+= psmouse.o
 obj-$(CONFIG_MOUSE_SERIAL)	+= sermouse.o
+obj-$(CONFIG_MOUSE_HIL)		+= hil_ptr.o
 obj-$(CONFIG_MOUSE_VSXXXAA)	+= vsxxxaa.o
 
 psmouse-objs  := psmouse-base.o logips2pp.o synaptics.o
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/mouse/hil_ptr.c parisc-2.6-bk/drivers/input/mouse/hil_ptr.c
--- linux-2.6.10-rc1-bk13/drivers/input/mouse/hil_ptr.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/drivers/input/mouse/hil_ptr.c	Wed Nov  3 06:12:03 2004
@@ -0,0 +1,414 @@
+/*
+ * Generic linux-input device driver for axis-bearing devices
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/input.h>
+#include <linux/serio.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/pci_ids.h>
+
+#define PREFIX "HIL PTR: "
+#define HIL_GENERIC_NAME "HIL pointer device"
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION(HIL_GENERIC_NAME " driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+
+#define TABLET_SIMULATES_MOUSE	/* allow tablet to be used as mouse */
+#undef  TABLET_AUTOADJUST	/* auto-adjust valid tablet ranges */
+
+
+#define HIL_PTR_MAX_LENGTH 16
+
+struct hil_ptr {
+	struct input_dev dev;
+	struct serio *serio;
+
+	/* Input buffer and index for packets from HIL bus. */
+	hil_packet data[HIL_PTR_MAX_LENGTH];
+	int idx4; /* four counts per packet */
+
+	/* Raw device info records from HIL bus, see hil.h for fields. */
+	char	idd[HIL_PTR_MAX_LENGTH];	/* DID byte and IDD record */
+	char	rsc[HIL_PTR_MAX_LENGTH];	/* RSC record */
+	char	exd[HIL_PTR_MAX_LENGTH];	/* EXD record */
+	char	rnm[HIL_PTR_MAX_LENGTH + 1];	/* RNM record + NULL term. */
+
+	/* Extra device details not contained in struct input_dev. */
+	unsigned int nbtn, naxes;
+	unsigned int btnmap[7];
+
+	/* Something to sleep around with. */
+	struct semaphore sem;
+};
+
+/* Process a complete packet after transfer from the HIL */
+static void hil_ptr_process_record(struct hil_ptr *ptr)
+{
+	struct input_dev *dev = &ptr->dev;
+	hil_packet *data = ptr->data;
+	hil_packet p;
+	int idx, i, cnt, laxis;
+	int ax16, absdev;
+
+	idx = ptr->idx4/4;
+	p = data[idx - 1];
+
+	if ((p & ~HIL_CMDCT_POL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) goto report;
+	if ((p & ~HIL_CMDCT_RPL) == 
+	    (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_RPL)) goto report;
+
+	/* Not a poll response.  See if we are loading config records. */
+	switch (p & HIL_PKT_DATA_MASK) {
+	case HIL_CMD_IDD:
+		for (i = 0; i < idx; i++)
+			ptr->idd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH; i++)
+			ptr->idd[i] = 0;
+		break;
+	case HIL_CMD_RSC:
+		for (i = 0; i < idx; i++)
+			ptr->rsc[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH; i++)
+			ptr->rsc[i] = 0;
+		break;
+	case HIL_CMD_EXD:
+		for (i = 0; i < idx; i++)
+			ptr->exd[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH; i++)
+			ptr->exd[i] = 0;
+		break;
+	case HIL_CMD_RNM:
+		for (i = 0; i < idx; i++)
+			ptr->rnm[i] = ptr->data[i] & HIL_PKT_DATA_MASK;
+		for (; i < HIL_PTR_MAX_LENGTH + 1; i++)
+			ptr->rnm[i] = '\0';
+		break;
+	default:
+		/* These occur when device isn't present */
+		if (p == (HIL_ERR_INT | HIL_PKT_CMD)) break; 
+		/* Anything else we'd like to know about. */
+		printk(KERN_WARNING PREFIX "Device sent unknown record %x\n", p);
+		break;
+	}
+	goto out;
+
+ report:
+	if ((p & HIL_CMDCT_POL) != idx - 1) {
+		printk(KERN_WARNING PREFIX "Malformed poll packet %x (idx = %i)\n", p, idx);
+		goto out;
+	}
+
+	i = (ptr->data[0] & HIL_POL_AXIS_ALT) ? 3 : 0;
+	laxis = ptr->data[0] & HIL_POL_NUM_AXES_MASK;
+	laxis += i;
+
+	ax16 = ptr->idd[1] & HIL_IDD_HEADER_16BIT; /* 8 or 16bit resolution */
+	absdev = ptr->idd[1] & HIL_IDD_HEADER_ABS; 
+
+	for (cnt = 1; i < laxis; i++) {
+		unsigned int lo,hi,val;
+		lo = ptr->data[cnt++] & HIL_PKT_DATA_MASK;
+		hi = ax16 ? (ptr->data[cnt++] & HIL_PKT_DATA_MASK) : 0;
+		if (absdev) {
+			val = lo + (hi<<8);
+#ifdef TABLET_AUTOADJUST
+			if (val < ptr->dev.absmin[ABS_X + i])
+				ptr->dev.absmin[ABS_X + i] = val;
+			if (val > ptr->dev.absmax[ABS_X + i])
+				ptr->dev.absmax[ABS_X + i] = val;
+#endif
+			if (i%3) val = ptr->dev.absmax[ABS_X + i] - val;
+			input_report_abs(dev, ABS_X + i, val);
+		} else {
+			val = (int) (((int8_t)lo) | ((int8_t)hi<<8));
+			if (i%3) val *= -1;
+			input_report_rel(dev, REL_X + i, val);
+		}
+	}
+
+	while (cnt < idx - 1) {
+		unsigned int btn;
+		int up;
+		btn = ptr->data[cnt++];
+		up = btn & 1;
+		btn &= 0xfe;
+		if (btn == 0x8e) {
+			continue; /* TODO: proximity == touch? */
+		}
+		else if ((btn > 0x8c) || (btn < 0x80)) continue;
+		btn = (btn - 0x80) >> 1;
+		btn = ptr->btnmap[btn];
+		input_report_key(dev, btn, !up);
+	}
+	input_sync(dev);
+ out:
+	ptr->idx4 = 0;
+	up(&ptr->sem);
+}
+
+static void hil_ptr_process_err(struct hil_ptr *ptr) {
+	printk(KERN_WARNING PREFIX "errored HIL packet\n");
+	ptr->idx4 = 0;
+	up(&ptr->sem);
+	return;
+}
+
+static irqreturn_t hil_ptr_interrupt(struct serio *serio, 
+        unsigned char data, unsigned int flags, struct pt_regs *regs)
+{
+	struct hil_ptr *ptr;
+	hil_packet packet;
+	int idx;
+
+	ptr = (struct hil_ptr *)serio->private;
+	if (ptr == NULL) {
+		BUG();
+		return IRQ_HANDLED;
+	}
+
+	if (ptr->idx4 >= (HIL_PTR_MAX_LENGTH * sizeof(hil_packet))) {
+		hil_ptr_process_err(ptr);
+		return IRQ_HANDLED;
+	}
+	idx = ptr->idx4/4;
+	if (!(ptr->idx4 % 4)) ptr->data[idx] = 0;
+	packet = ptr->data[idx];
+	packet |= ((hil_packet)data) << ((3 - (ptr->idx4 % 4)) * 8);
+	ptr->data[idx] = packet;
+
+	/* Records of N 4-byte hil_packets must terminate with a command. */
+	if ((++(ptr->idx4)) % 4) return IRQ_HANDLED;
+	if ((packet & 0xffff0000) != HIL_ERR_INT) {
+		hil_ptr_process_err(ptr);
+		return IRQ_HANDLED;
+	}
+	if (packet & HIL_PKT_CMD) 
+		hil_ptr_process_record(ptr);
+	return IRQ_HANDLED;
+}
+
+static void hil_ptr_disconnect(struct serio *serio)
+{
+	struct hil_ptr *ptr;
+
+	ptr = (struct hil_ptr *)serio->private;
+	if (ptr == NULL) {
+		BUG();
+		return;
+	}
+
+	input_unregister_device(&ptr->dev);
+	serio_close(serio);
+	kfree(ptr);
+}
+
+static void hil_ptr_connect(struct serio *serio, struct serio_driver *driver)
+{
+	struct hil_ptr	*ptr;
+	char		*txt;
+	unsigned int	i, naxsets, btntype;
+	uint8_t		did, *idd;
+
+	if (serio->type != (SERIO_HIL_MLC | SERIO_HIL)) return;
+
+	if (!(ptr = kmalloc(sizeof(struct hil_ptr), GFP_KERNEL))) return;
+	memset(ptr, 0, sizeof(struct hil_ptr));
+
+	if (serio_open(serio, driver)) goto bail0;
+
+	serio->private = ptr;
+	ptr->serio = serio;
+	ptr->dev.private = ptr;
+
+	init_MUTEX_LOCKED(&(ptr->sem));
+
+	/* Get device info.  MLC driver supplies devid/status/etc. */
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_IDD);
+	down(&(ptr->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RSC);
+	down(&(ptr->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_RNM);
+	down(&(ptr->sem));
+
+	serio->write(serio, 0);
+	serio->write(serio, 0);
+	serio->write(serio, HIL_PKT_CMD >> 8);
+	serio->write(serio, HIL_CMD_EXD);
+	down(&(ptr->sem));
+
+	up(&(ptr->sem));
+
+	init_input_dev(&ptr->dev);
+	did = ptr->idd[0];
+	idd = ptr->idd + 1;
+	txt = "unknown";
+	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
+		ptr->dev.evbit[0] = BIT(EV_REL);
+		txt = "relative";
+	}
+
+	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_ABS) {
+		ptr->dev.evbit[0] = BIT(EV_ABS);
+		txt = "absolute";
+	}
+	if (!ptr->dev.evbit[0]) {
+		goto bail1;
+	}
+
+	ptr->nbtn = HIL_IDD_NUM_BUTTONS(idd);
+	if (ptr->nbtn) ptr->dev.evbit[0] |= BIT(EV_KEY);
+
+	naxsets = HIL_IDD_NUM_AXSETS(*idd);
+	ptr->naxes = HIL_IDD_NUM_AXES_PER_SET(*idd);
+
+	printk(KERN_INFO PREFIX "HIL pointer device found (did: 0x%02x, axis: %s)\n",
+			did, txt);
+	printk(KERN_INFO PREFIX "HIL pointer has %i buttons and %i sets of %i axes\n",
+			ptr->nbtn, naxsets, ptr->naxes);
+	
+	btntype = BTN_MISC;
+	if ((did & HIL_IDD_DID_ABS_TABLET_MASK) == HIL_IDD_DID_ABS_TABLET)
+#ifdef TABLET_SIMULATES_MOUSE
+		btntype = BTN_TOUCH;
+#else
+		btntype = BTN_DIGI;
+#endif
+	if ((did & HIL_IDD_DID_ABS_TSCREEN_MASK) == HIL_IDD_DID_ABS_TSCREEN)
+		btntype = BTN_TOUCH;
+		
+	if ((did & HIL_IDD_DID_REL_MOUSE_MASK) == HIL_IDD_DID_REL_MOUSE)
+		btntype = BTN_MOUSE;
+
+	for (i = 0; i < ptr->nbtn; i++) {
+		set_bit(btntype | i, ptr->dev.keybit);
+		ptr->btnmap[i] = btntype | i;
+	}
+
+	if (btntype == BTN_MOUSE) {
+		/* Swap buttons 2 and 3 */
+		ptr->btnmap[1] = BTN_MIDDLE;
+		ptr->btnmap[2] = BTN_RIGHT;
+	}
+
+	if ((did & HIL_IDD_DID_TYPE_MASK) == HIL_IDD_DID_TYPE_REL) {
+		for (i = 0; i < ptr->naxes; i++) {
+			set_bit(REL_X + i, ptr->dev.relbit);
+		}
+		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+			set_bit(REL_X + i, ptr->dev.relbit);
+		}
+	} else {
+		for (i = 0; i < ptr->naxes; i++) {
+	  		set_bit(ABS_X + i, ptr->dev.absbit);
+			ptr->dev.absmin[ABS_X + i] = 0;
+			ptr->dev.absmax[ABS_X + i] = 
+				HIL_IDD_AXIS_MAX((ptr->idd + 1), i);
+		}
+		for (i = 3; (i < ptr->naxes + 3) && (naxsets > 1); i++) {
+			set_bit(ABS_X + i, ptr->dev.absbit);
+			ptr->dev.absmin[ABS_X + i] = 0;
+			ptr->dev.absmax[ABS_X + i] = 
+				HIL_IDD_AXIS_MAX((ptr->idd + 1), (i - 3));
+		}
+#ifdef TABLET_AUTOADJUST
+		for (i = 0; i < ABS_MAX; i++) {
+			int diff = ptr->dev.absmax[ABS_X + i] / 10;
+			ptr->dev.absmin[ABS_X + i] += diff;
+			ptr->dev.absmax[ABS_X + i] -= diff;
+		}
+#endif
+	}
+
+	ptr->dev.name = strlen(ptr->rnm) ? ptr->rnm : HIL_GENERIC_NAME;
+
+	ptr->dev.id.bustype	= BUS_HIL;
+	ptr->dev.id.vendor	= PCI_VENDOR_ID_HP;
+	ptr->dev.id.product	= 0x0001; /* TODO: get from ptr->rsc */
+	ptr->dev.id.version	= 0x0100; /* TODO: get from ptr->rsc */
+	ptr->dev.dev		= &serio->dev;
+
+	input_register_device(&ptr->dev);
+	printk(KERN_INFO "input: %s (%s), ID: %d\n",
+                ptr->dev.name, 
+		(btntype == BTN_MOUSE) ? "HIL mouse":"HIL tablet or touchpad",
+		did);
+
+	return;
+ bail1:
+	serio_close(serio);
+ bail0:
+	kfree(ptr);
+	return;
+}
+
+
+static struct serio_driver hil_ptr_serio_driver = {
+	.driver		= {
+		.name	= "hil_ptr",
+	},
+	.description	= "HP HIL mouse/tablet driver",
+	.connect =	hil_ptr_connect,
+	.disconnect =	hil_ptr_disconnect,
+	.interrupt =	hil_ptr_interrupt
+};
+
+static int __init hil_ptr_init(void)
+{
+	serio_register_driver(&hil_ptr_serio_driver);
+        return 0;
+}
+                
+static void __exit hil_ptr_exit(void)
+{
+	serio_unregister_driver(&hil_ptr_serio_driver);
+}
+                        
+module_init(hil_ptr_init);
+module_exit(hil_ptr_exit);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/serio/Kconfig parisc-2.6-bk/drivers/input/serio/Kconfig
--- linux-2.6.10-rc1-bk13/drivers/input/serio/Kconfig	Wed Nov  3 05:57:45 2004
+++ parisc-2.6-bk/drivers/input/serio/Kconfig	Wed Nov  3 06:19:01 2004
@@ -48,8 +48,7 @@ config SERIO_SERPORT
 
 config SERIO_CT82C710
 	tristate "ct82c710 Aux port controller"
-	depends on SERIO
-	depends on !PARISC
+	depends on X86 && SERIO
 	---help---
 	  Say Y here if you have a Texas Instruments TravelMate notebook
 	  equipped with the ct82c710 chip and want to use a mouse connected
@@ -110,6 +109,32 @@ config SERIO_GSCPS2
 
 	  To compile this driver as a module, choose M here: the
 	  module will be called gscps2.
+
+config HP_SDC
+	tristate "HP System Device Controller i8042 Support"
+	depends on GSC && SERIO
+	default y
+	---help---
+	  This option enables supports for the the "System Device
+	  Controller", an i8042 carrying microcode to manage a
+	  few miscellanous devices on some Hewlett Packard systems.
+	  The SDC itself contains a 10ms resolution timer/clock capable
+	  of delivering interrupts on a periodic and one-shot basis.
+	  The SDC may also be connected to a battery-backed real-time
+	  clock, a basic audio waveform generator, and an HP-HIL Master
+	  Link Controller serving up to seven input devices.
+
+	  By itself this option is rather useless, but enabling it will
+	  enable selection of drivers for the abovementioned devices.
+	  It is, however, incompatible with the old, reliable HIL keyboard
+	  driver, and the new HIL driver is experimental, so if you plan
+	  to use a HIL keyboard as your primary keyboard, you may wish
+	  to keep using that driver until the new HIL drivers have had
+	  more testing.
+
+config HIL_MLC
+	tristate "HIL MLC Support (needed for HIL input devices)"
+	depends on HP_SDC
 
 config SERIO_PCIPS2
 	tristate "PCI PS/2 keyboard and PS/2 mouse controller"
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/serio/Makefile parisc-2.6-bk/drivers/input/serio/Makefile
--- linux-2.6.10-rc1-bk13/drivers/input/serio/Makefile	Fri Oct 22 15:38:16 2004
+++ parisc-2.6-bk/drivers/input/serio/Makefile	Wed Nov  3 06:19:01 2004
@@ -2,8 +2,6 @@
 # Makefile for the input core drivers.
 #
 
-# Each configuration option enables a list of files.
-
 obj-$(CONFIG_SERIO)		+= serio.o
 obj-$(CONFIG_SERIO_I8042)	+= i8042.o
 obj-$(CONFIG_SERIO_PARKBD)	+= parkbd.o
@@ -15,6 +13,8 @@ obj-$(CONFIG_SERIO_AMBAKMI)	+= ambakmi.o
 obj-$(CONFIG_SERIO_Q40KBD)	+= q40kbd.o
 obj-$(CONFIG_SERIO_98KBD)	+= 98kbd-io.o
 obj-$(CONFIG_SERIO_GSCPS2)	+= gscps2.o
+obj-$(CONFIG_HP_SDC)		+= hp_sdc.o
+obj-$(CONFIG_HIL_MLC)		+= hp_sdc_mlc.o hil_mlc.o
 obj-$(CONFIG_SERIO_PCIPS2)	+= pcips2.o
 obj-$(CONFIG_SERIO_MACEPS2)	+= maceps2.o
 obj-$(CONFIG_SERIO_RAW)		+= serio_raw.o
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/serio/gscps2.c parisc-2.6-bk/drivers/input/serio/gscps2.c
--- linux-2.6.10-rc1-bk13/drivers/input/serio/gscps2.c	Fri Oct 22 15:40:29 2004
+++ parisc-2.6-bk/drivers/input/serio/gscps2.c	Wed Nov  3 06:19:02 2004
@@ -38,7 +38,7 @@
 #include <asm/parisc-device.h>
 
 MODULE_AUTHOR("Laurent Canet <canetl@esiee.fr>, Thibaut Varene <varenet@esiee.fr>, Helge Deller <deller@gmx.de>");
-MODULE_DESCRIPTION("HP GSC PS/2 port driver");
+MODULE_DESCRIPTION("HP GSC PS2 port driver");
 MODULE_LICENSE("GPL");
 MODULE_DEVICE_TABLE(parisc, gscps2_device_tbl);
 
@@ -322,19 +322,6 @@ static void gscps2_close(struct serio *p
 	gscps2_enable(ps2port, DISABLE);
 }
 
-static struct serio gscps2_serio_port =
-{
-	.name =		"GSC PS/2",
-	.idbus =	BUS_GSC,
-	.idvendor =	PCI_VENDOR_ID_HP,
-	.idproduct =	0x0001,
-	.idversion =	0x0010,
-	.type =		SERIO_8042,
-	.write =	gscps2_write,
-	.open =		gscps2_open,
-	.close =	gscps2_close,
-};
-
 /**
  * gscps2_probe() - Probes PS2 devices
  * @return: success/error report
@@ -461,7 +448,7 @@ static struct parisc_device_id gscps2_de
 };
 
 static struct parisc_driver parisc_ps2_driver = {
-	.name		= "GSC PS/2",
+	.name		= "GSC PS2",
 	.id_table	= gscps2_device_tbl,
 	.probe		= gscps2_probe,
 	.remove		= gscps2_remove,
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/serio/hil_mlc.c parisc-2.6-bk/drivers/input/serio/hil_mlc.c
--- linux-2.6.10-rc1-bk13/drivers/input/serio/hil_mlc.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/drivers/input/serio/hil_mlc.c	Wed Nov  3 06:12:03 2004
@@ -0,0 +1,949 @@
+/*
+ * HIL MLC state machine and serio interface driver
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ *
+ *	Driver theory of operation:
+ *
+ *	Some access methods and an ISR is defined by the sub-driver 
+ *	(e.g. hp_sdc_mlc.c).  These methods are expected to provide a 
+ *	few bits of logic in addition to raw access to the HIL MLC, 
+ *	specifically, the ISR, which is entirely registered by the 
+ *	sub-driver and invoked directly, must check for record 
+ *	termination or packet match, at which point a semaphore must
+ *	be cleared and then the hil_mlcs_tasklet must be scheduled.
+ *
+ *	The hil_mlcs_tasklet processes the state machine for all MLCs
+ *	each time it runs, checking each MLC's progress at the current
+ *	node in the state machine, and moving the MLC to subsequent nodes
+ *	in the state machine when appropriate.  It will reschedule
+ *	itself if output is pending.  (This rescheduling should be replaced
+ *	at some point with a sub-driver-specific mechanism.)
+ *
+ *	A timer task prods the tasklet once per second to prevent 
+ *	hangups when attached devices do not return expected data
+ *	and to initiate probes of the loop for new devices.
+ */
+
+#include <linux/hil_mlc.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/timer.h>
+#include <linux/sched.h>
+#include <linux/list.h>
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HIL MLC serio");
+MODULE_LICENSE("Dual BSD/GPL");
+
+EXPORT_SYMBOL(hil_mlc_register);
+EXPORT_SYMBOL(hil_mlc_unregister);
+
+#define PREFIX "HIL MLC: "
+
+static LIST_HEAD(hil_mlcs);
+static rwlock_t			hil_mlcs_lock = RW_LOCK_UNLOCKED;
+static struct timer_list	hil_mlcs_kicker;
+static int			hil_mlcs_probe;
+
+static void hil_mlcs_process(unsigned long unused);
+DECLARE_TASKLET_DISABLED(hil_mlcs_tasklet, hil_mlcs_process, 0);
+
+
+/* #define HIL_MLC_DEBUG */
+
+/********************** Device info/instance management **********************/
+
+static void hil_mlc_clear_di_map (hil_mlc *mlc, int val) {
+	int j;
+	for (j = val; j < 7 ; j++) {
+		mlc->di_map[j] = -1;
+	}
+}
+
+static void hil_mlc_clear_di_scratch (hil_mlc *mlc) {
+	memset(&(mlc->di_scratch), 0, sizeof(mlc->di_scratch));
+}
+
+static void hil_mlc_copy_di_scratch (hil_mlc *mlc, int idx) {
+	memcpy(&(mlc->di[idx]), &(mlc->di_scratch), sizeof(mlc->di_scratch));
+}
+
+static int hil_mlc_match_di_scratch (hil_mlc *mlc) {
+	int idx;
+
+	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+		int j, found;
+
+		/* In-use slots are not eligible. */
+		found = 0;
+		for (j = 0; j < 7 ; j++) {
+			if (mlc->di_map[j] == idx) found++;
+		}
+		if (found) continue;
+		if (!memcmp(mlc->di + idx, 
+			    &(mlc->di_scratch), 
+			    sizeof(mlc->di_scratch))) break;
+	}
+	return((idx >= HIL_MLC_DEVMEM) ? -1 : idx);
+}
+
+static int hil_mlc_find_free_di(hil_mlc *mlc) {
+	int idx;
+	/* TODO: Pick all-zero slots first, failing that, 
+	 * randomize the slot picked among those eligible. 
+	 */
+	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+		int j, found;
+		found = 0;
+		for (j = 0; j < 7 ; j++) {
+			if (mlc->di_map[j] == idx) found++;
+		}
+		if (!found) break;
+	}
+	return(idx); /* Note: It is guaranteed at least one above will match */
+}
+
+static inline void hil_mlc_clean_serio_map(hil_mlc *mlc) {
+	int idx;
+	for (idx = 0; idx < HIL_MLC_DEVMEM; idx++) {
+		int j, found;
+		found = 0;
+		for (j = 0; j < 7 ; j++) {
+			if (mlc->di_map[j] == idx) found++;
+		}
+		if (!found) mlc->serio_map[idx].di_revmap = -1;
+	}
+}
+
+static void hil_mlc_send_polls(hil_mlc *mlc) {
+	int did, i, cnt;
+	struct serio *serio;
+	struct serio_driver *drv;
+
+	i = cnt = 0;
+	did = (mlc->ipacket[0] & HIL_PKT_ADDR_MASK) >> 8;
+	serio = did ? mlc->serio[mlc->di_map[did - 1]] : NULL;
+	drv = (serio != NULL) ? serio->drv : NULL;
+
+	while (mlc->icount < 15 - i) {
+		hil_packet p;
+		p = mlc->ipacket[i];
+		if (did != (p & HIL_PKT_ADDR_MASK) >> 8) {
+			if (drv == NULL || drv->interrupt == NULL) goto skip;
+
+			drv->interrupt(serio, 0, 0, NULL);
+			drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+			drv->interrupt(serio, HIL_PKT_CMD >> 8,  0, NULL);
+			drv->interrupt(serio, HIL_CMD_POL + cnt, 0, NULL);
+		skip:
+			did = (p & HIL_PKT_ADDR_MASK) >> 8;
+			serio = did ? mlc->serio[mlc->di_map[did-1]] : NULL;
+			drv = (serio != NULL) ? serio->drv : NULL;
+			cnt = 0;
+		}
+		cnt++; i++;
+		if (drv == NULL || drv->interrupt == NULL) continue;
+		drv->interrupt(serio, (p >> 24), 0, NULL);
+		drv->interrupt(serio, (p >> 16) & 0xff, 0, NULL);
+		drv->interrupt(serio, (p >> 8) & ~HIL_PKT_ADDR_MASK, 0, NULL);
+		drv->interrupt(serio, p & 0xff, 0, NULL);
+	}
+}
+
+/*************************** State engine *********************************/
+
+#define HILSEN_SCHED	0x000100	/* Schedule the tasklet		*/
+#define HILSEN_BREAK	0x000200	/* Wait until next pass		*/
+#define HILSEN_UP	0x000400	/* relative node#, decrement	*/
+#define HILSEN_DOWN	0x000800	/* relative node#, increment	*/
+#define HILSEN_FOLLOW	0x001000	/* use retval as next node#	*/
+
+#define HILSEN_MASK	0x0000ff
+#define HILSEN_START	0
+#define HILSEN_RESTART	1
+#define HILSEN_DHR	9
+#define HILSEN_DHR2	10
+#define HILSEN_IFC	14
+#define HILSEN_HEAL0	16
+#define HILSEN_HEAL	18
+#define HILSEN_ACF      21
+#define HILSEN_ACF2	22
+#define HILSEN_DISC0	25
+#define HILSEN_DISC	27
+#define HILSEN_MATCH	40
+#define HILSEN_OPERATE	41
+#define HILSEN_PROBE	44
+#define HILSEN_DSR	52
+#define HILSEN_REPOLL	55
+#define HILSEN_IFCACF	58
+#define HILSEN_END	60
+
+#define HILSEN_NEXT	(HILSEN_DOWN | 1)
+#define HILSEN_SAME	(HILSEN_DOWN | 0)
+#define HILSEN_LAST	(HILSEN_UP | 1)
+
+#define HILSEN_DOZE	(HILSEN_SAME | HILSEN_SCHED | HILSEN_BREAK)
+#define HILSEN_SLEEP	(HILSEN_SAME | HILSEN_BREAK)
+
+static int hilse_match(hil_mlc *mlc, int unused) {
+	int rc;
+	rc = hil_mlc_match_di_scratch(mlc);
+	if (rc == -1) {
+		rc = hil_mlc_find_free_di(mlc);
+		if (rc == -1) goto err;
+#ifdef HIL_MLC_DEBUG
+		printk(KERN_DEBUG PREFIX "new in slot %i\n", rc);
+#endif
+		hil_mlc_copy_di_scratch(mlc, rc);
+		mlc->di_map[mlc->ddi] = rc;
+		mlc->serio_map[rc].di_revmap = mlc->ddi;
+		hil_mlc_clean_serio_map(mlc);
+		serio_rescan(mlc->serio[rc]);
+		return -1;
+	}
+	mlc->di_map[mlc->ddi] = rc;
+#ifdef HIL_MLC_DEBUG
+	printk(KERN_DEBUG PREFIX "same in slot %i\n", rc);
+#endif
+	mlc->serio_map[rc].di_revmap = mlc->ddi;
+	hil_mlc_clean_serio_map(mlc);
+	return 0;
+ err:
+	printk(KERN_ERR PREFIX "Residual device slots exhausted, close some serios!\n");
+	return 1;
+}
+
+/* An LCV used to prevent runaway loops, forces 5 second sleep when reset. */
+static int hilse_init_lcv(hil_mlc *mlc, int unused) {
+	struct timeval tv;
+
+	do_gettimeofday(&tv);
+
+	if(mlc->lcv == 0) goto restart;  /* First init, no need to dally */
+	if(tv.tv_sec - mlc->lcv_tv.tv_sec < 5) return -1;
+ restart:
+	mlc->lcv_tv = tv;
+	mlc->lcv = 0;
+	return 0;
+}
+
+static int hilse_inc_lcv(hil_mlc *mlc, int lim) {
+	if (mlc->lcv++ >= lim) return -1;
+	return 0;
+}
+
+#if 0
+static int hilse_set_lcv(hil_mlc *mlc, int val) {
+	mlc->lcv = val;
+	return 0;
+}
+#endif
+
+/* Management of the discovered device index (zero based, -1 means no devs) */
+static int hilse_set_ddi(hil_mlc *mlc, int val) {
+	mlc->ddi = val;
+	hil_mlc_clear_di_map(mlc, val + 1);
+	return 0;
+}
+
+static int hilse_dec_ddi(hil_mlc *mlc, int unused) {
+	mlc->ddi--;
+	if (mlc->ddi <= -1) { 
+		mlc->ddi = -1;
+		hil_mlc_clear_di_map(mlc, 0);
+		return -1;
+	}
+	hil_mlc_clear_di_map(mlc, mlc->ddi + 1);
+	return 0;
+}
+
+static int hilse_inc_ddi(hil_mlc *mlc, int unused) {
+	if (mlc->ddi >= 6) {
+		BUG();
+		return -1;
+	}
+	mlc->ddi++;
+	return 0;
+}
+
+static int hilse_take_idd(hil_mlc *mlc, int unused) {
+	int i;
+
+	/* Help the state engine: 
+	 * Is this a real IDD response or just an echo? 
+	 *
+	 * Real IDD response does not start with a command. 
+	 */
+	if (mlc->ipacket[0] & HIL_PKT_CMD) goto bail;
+	/* Should have the command echoed further down. */
+	for (i = 1; i < 16; i++) {
+		if (((mlc->ipacket[i] & HIL_PKT_ADDR_MASK) == 
+		     (mlc->ipacket[0] & HIL_PKT_ADDR_MASK)) &&
+		    (mlc->ipacket[i] & HIL_PKT_CMD) && 
+		    ((mlc->ipacket[i] & HIL_PKT_DATA_MASK) == HIL_CMD_IDD))
+			break;
+	}
+	if (i > 15) goto bail;
+	/* And the rest of the packets should still be clear. */
+	while (++i < 16) {
+		if (mlc->ipacket[i]) break;
+	}
+	if (i < 16) goto bail;
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.idd[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	/* Next step is to see if RSC supported */
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_RSC) 
+		return HILSEN_NEXT;
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+		return HILSEN_DOWN | 4;
+	return 0;
+ bail:
+	mlc->ddi--;
+	return -1; /* This should send us off to ACF */
+}
+
+static int hilse_take_rsc(hil_mlc *mlc, int unused) {
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.rsc[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	/* Next step is to see if EXD supported (IDD has already been read) */
+	if (mlc->di_scratch.idd[1] & HIL_IDD_HEADER_EXD) 
+		return HILSEN_NEXT;
+	return 0;
+}
+
+static int hilse_take_exd(hil_mlc *mlc, int unused) {
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.exd[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	/* Next step is to see if RNM supported. */
+	if (mlc->di_scratch.exd[0] & HIL_EXD_HEADER_RNM) 
+		return HILSEN_NEXT;
+	return 0;
+}
+
+static int hilse_take_rnm(hil_mlc *mlc, int unused) {
+	int i;
+
+	for (i = 0; i < 16; i++) {
+		mlc->di_scratch.rnm[i] = 
+			mlc->ipacket[i] & HIL_PKT_DATA_MASK;
+	}
+	do {
+	  char nam[17];
+	  snprintf(nam, 16, "%s", mlc->di_scratch.rnm);
+	  nam[16] = '\0';
+	  printk(KERN_INFO PREFIX "Device name gotten: %s\n", nam);
+	} while (0);
+	return 0;
+}
+
+static int hilse_operate(hil_mlc *mlc, int repoll) { 
+
+	if (mlc->opercnt == 0) hil_mlcs_probe = 0;
+	mlc->opercnt = 1;
+
+	hil_mlc_send_polls(mlc);
+
+	if (!hil_mlcs_probe) return 0;
+	hil_mlcs_probe = 0;
+	mlc->opercnt = 0;
+	return 1;
+}
+
+#define FUNC(funct, funct_arg, zero_rc, neg_rc, pos_rc) \
+{ HILSE_FUNC,		{ func: &funct }, funct_arg, zero_rc, neg_rc, pos_rc },
+#define OUT(pack) \
+{ HILSE_OUT,		{ packet: pack }, 0, HILSEN_NEXT, HILSEN_DOZE, 0 },
+#define CTS \
+{ HILSE_CTS,		{ packet: 0    }, 0, HILSEN_NEXT | HILSEN_SCHED | HILSEN_BREAK, HILSEN_DOZE, 0 },
+#define EXPECT(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT,		{ packet: comp }, to, got, got_wrong, timed_out },
+#define EXPECT_LAST(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT_LAST,	{ packet: comp }, to, got, got_wrong, timed_out },
+#define EXPECT_DISC(comp, to, got, got_wrong, timed_out) \
+{ HILSE_EXPECT_DISC,	{ packet: comp }, to, got, got_wrong, timed_out },
+#define IN(to, got, got_error, timed_out) \
+{ HILSE_IN,		{ packet: 0    }, to, got, got_error, timed_out },
+#define OUT_DISC(pack) \
+{ HILSE_OUT_DISC,	{ packet: pack }, 0, 0, 0, 0 },
+#define OUT_LAST(pack) \
+{ HILSE_OUT_LAST,	{ packet: pack }, 0, 0, 0, 0 },
+
+struct hilse_node hil_mlc_se[HILSEN_END] = {
+
+	/* 0  HILSEN_START */
+	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
+
+	/* 1  HILSEN_RESTART */
+	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,  0)
+	OUT(HIL_CTRL_ONLY)			/* Disable APE */
+	CTS
+
+#define TEST_PACKET(x) \
+(HIL_PKT_CMD | (x << HIL_PKT_ADDR_SHIFT) | x << 4 | x)
+
+	OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0x5))
+	EXPECT(HIL_ERR_INT | TEST_PACKET(0x5),
+	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
+	OUT(HIL_DO_ALTER_CTRL | HIL_CTRL_TEST | TEST_PACKET(0xa))
+	EXPECT(HIL_ERR_INT | TEST_PACKET(0xa),
+	       2000,		HILSEN_NEXT,	HILSEN_RESTART,	HILSEN_RESTART)
+	OUT(HIL_CTRL_ONLY | 0)			/* Disable test mode */
+	
+	/* 9  HILSEN_DHR */
+	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_SLEEP,	0)
+
+	/* 10 HILSEN_DHR2 */
+	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
+	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
+	OUT(HIL_PKT_CMD | HIL_CMD_DHR)
+	IN(300000,		HILSEN_DHR2,	HILSEN_DHR2,	HILSEN_NEXT)
+
+	/* 14 HILSEN_IFC */
+  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
+	       20000,		HILSEN_DISC,	HILSEN_DHR2,	HILSEN_NEXT )
+
+	/* If devices are there, they weren't in PUP or other loopback mode.
+	 * We're more concerned at this point with restoring operation
+	 * to devices than discovering new ones, so we try to salvage
+	 * the loop configuration by closing off the loop.
+	 */
+
+	/* 16 HILSEN_HEAL0 */
+	FUNC(hilse_dec_ddi, 0,	HILSEN_NEXT,	HILSEN_ACF,	0)
+	FUNC(hilse_inc_ddi, 0,	HILSEN_NEXT,	0,		0)
+
+	/* 18 HILSEN_HEAL */
+	OUT_LAST(HIL_CMD_ELB)
+	EXPECT_LAST(HIL_CMD_ELB | HIL_ERR_INT, 
+		    20000,	HILSEN_REPOLL,	HILSEN_DSR,	HILSEN_NEXT)
+	FUNC(hilse_dec_ddi, 0,	HILSEN_HEAL,	HILSEN_NEXT,	0)
+
+	/* 21 HILSEN_ACF */
+	FUNC(hilse_init_lcv, 0,	HILSEN_NEXT,	HILSEN_DOZE,	0)
+
+	/* 22 HILSEN_ACF2 */
+	FUNC(hilse_inc_lcv, 10,	HILSEN_NEXT,	HILSEN_START,	0)
+	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
+	IN(20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
+
+	/* 25 HILSEN_DISC0 */
+	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
+	EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_ELB | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+
+	/* Only enter here if response just received */
+	/* 27 HILSEN_DISC */
+	OUT_DISC(HIL_PKT_CMD | HIL_CMD_IDD)
+	EXPECT_DISC(HIL_PKT_CMD | HIL_CMD_IDD | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_START)
+	FUNC(hilse_inc_ddi,  0,	HILSEN_NEXT,	HILSEN_START,	0)
+	FUNC(hilse_take_idd, 0,	HILSEN_MATCH,	HILSEN_IFCACF,	HILSEN_FOLLOW)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RSC)
+	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RSC | HIL_ERR_INT,
+	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+	FUNC(hilse_take_rsc, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EXD)
+	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_EXD | HIL_ERR_INT,
+	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+	FUNC(hilse_take_exd, 0,	HILSEN_MATCH,	0,		HILSEN_FOLLOW)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_RNM)
+	EXPECT_LAST(HIL_PKT_CMD | HIL_CMD_RNM | HIL_ERR_INT,
+	       30000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_DSR)
+	FUNC(hilse_take_rnm, 0, HILSEN_MATCH,	0,		0)
+
+	/* 40 HILSEN_MATCH */
+	FUNC(hilse_match, 0,	HILSEN_NEXT,	HILSEN_NEXT,	/* TODO */ 0)
+
+	/* 41 HILSEN_OPERATE */
+	OUT(HIL_PKT_CMD | HIL_CMD_POL)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_POL | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
+	FUNC(hilse_operate, 0,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_NEXT)
+
+	/* 44 HILSEN_PROBE */
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_EPT)
+	IN(10000, 		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
+	OUT_DISC(HIL_PKT_CMD | HIL_CMD_ELB)
+	IN(10000,		HILSEN_DISC,	HILSEN_DSR,	HILSEN_NEXT)
+	OUT(HIL_PKT_CMD | HIL_CMD_ACF | 1)
+	IN(10000,		HILSEN_DISC0,	HILSEN_DSR,	HILSEN_NEXT)
+	OUT_LAST(HIL_PKT_CMD | HIL_CMD_ELB)
+	IN(10000,		HILSEN_OPERATE,	HILSEN_DSR,	HILSEN_DSR)
+
+	/* 52 HILSEN_DSR */
+	FUNC(hilse_set_ddi, -1,	HILSEN_NEXT,	0,		0)
+	OUT(HIL_PKT_CMD | HIL_CMD_DSR)
+	IN(20000, 		HILSEN_DHR,	HILSEN_DHR,	HILSEN_IFC)
+
+	/* 55 HILSEN_REPOLL */
+	OUT(HIL_PKT_CMD | HIL_CMD_RPL)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_RPL | HIL_ERR_INT,
+	       20000,		HILSEN_NEXT,	HILSEN_DSR,	HILSEN_NEXT)
+	FUNC(hilse_operate, 1,	HILSEN_OPERATE,	HILSEN_IFC,	HILSEN_PROBE)
+
+	/* 58 HILSEN_IFCACF */
+  	OUT(HIL_PKT_CMD | HIL_CMD_IFC)
+	EXPECT(HIL_PKT_CMD | HIL_CMD_IFC | HIL_ERR_INT,
+	       20000,		HILSEN_ACF2,	HILSEN_DHR2,	HILSEN_HEAL)
+
+	/* 60 HILSEN_END */
+};
+
+static inline void hilse_setup_input(hil_mlc *mlc, struct hilse_node *node) {
+
+	switch (node->act) {
+	case HILSE_EXPECT_DISC:
+		mlc->imatch = node->object.packet;
+		mlc->imatch |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
+		break;
+	case HILSE_EXPECT_LAST:
+		mlc->imatch = node->object.packet;
+		mlc->imatch |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
+		break;
+	case HILSE_EXPECT:
+		mlc->imatch = node->object.packet;
+		break;
+	case HILSE_IN:
+		mlc->imatch = 0;
+		break;
+	default:
+		BUG();
+	}
+	mlc->istarted = 1;
+	mlc->intimeout = node->arg;
+	do_gettimeofday(&(mlc->instart));
+	mlc->icount = 15;
+	memset(mlc->ipacket, 0, 16 * sizeof(hil_packet));
+	if (down_trylock(&(mlc->isem))) BUG();
+
+	return;
+}
+
+#ifdef HIL_MLC_DEBUG
+static int doze = 0;
+static int seidx; /* For debug */
+static int kick = 1;
+#endif
+
+static int hilse_donode (hil_mlc *mlc) {
+	struct hilse_node *node;
+	int nextidx = 0;
+	int sched_long = 0;
+	unsigned long flags;
+
+#ifdef HIL_MLC_DEBUG
+	if (mlc->seidx && (mlc->seidx != seidx)  && mlc->seidx != 41 && mlc->seidx != 42 && mlc->seidx != 43) {
+	  printk(KERN_DEBUG PREFIX "z%i \n%s {%i}", doze, kick ? "K" : "", mlc->seidx);
+		doze = 0;
+	}
+	kick = 0;
+
+	seidx = mlc->seidx;
+#endif
+	node = hil_mlc_se + mlc->seidx;
+
+	switch (node->act) {
+		int rc;
+		hil_packet pack;
+
+	case HILSE_FUNC:
+		if (node->object.func == NULL) break;
+		rc = node->object.func(mlc, node->arg);
+		nextidx = (rc > 0) ? node->ugly : 
+			((rc < 0) ? node->bad : node->good);
+		if (nextidx == HILSEN_FOLLOW) nextidx = rc;
+		break;
+	case HILSE_EXPECT_LAST:
+	case HILSE_EXPECT_DISC:
+	case HILSE_EXPECT:
+	case HILSE_IN:
+		/* Already set up from previous HILSE_OUT_* */
+		write_lock_irqsave(&(mlc->lock), flags);
+		rc = mlc->in(mlc, node->arg);
+		if (rc == 2)  {
+			nextidx = HILSEN_DOZE;
+			sched_long = 1;
+			write_unlock_irqrestore(&(mlc->lock), flags);
+			break;
+		}
+		if (rc == 1)		nextidx = node->ugly;
+		else if (rc == 0)	nextidx = node->good;
+		else			nextidx = node->bad;
+		mlc->istarted = 0;
+		write_unlock_irqrestore(&(mlc->lock), flags);
+		break;
+	case HILSE_OUT_LAST:
+		write_lock_irqsave(&(mlc->lock), flags);
+		pack = node->object.packet;
+		pack |= ((mlc->ddi + 1) << HIL_PKT_ADDR_SHIFT);
+		goto out;
+	case HILSE_OUT_DISC:
+		write_lock_irqsave(&(mlc->lock), flags);
+		pack = node->object.packet;
+		pack |= ((mlc->ddi + 2) << HIL_PKT_ADDR_SHIFT);
+		goto out;
+	case HILSE_OUT:
+		write_lock_irqsave(&(mlc->lock), flags);
+		pack = node->object.packet;
+	out:
+		if (mlc->istarted) goto out2;
+		/* Prepare to receive input */
+		if ((node + 1)->act & HILSE_IN)
+			hilse_setup_input(mlc, node + 1);
+
+	out2:
+		write_unlock_irqrestore(&(mlc->lock), flags);
+
+		if (down_trylock(&mlc->osem)) {
+			nextidx = HILSEN_DOZE;
+			break;
+		}
+		up(&mlc->osem);
+
+		write_lock_irqsave(&(mlc->lock), flags);
+		if (!(mlc->ostarted)) {
+			mlc->ostarted = 1;
+			mlc->opacket = pack;
+			mlc->out(mlc);
+			nextidx = HILSEN_DOZE;
+			write_unlock_irqrestore(&(mlc->lock), flags);
+			break;
+		}
+		mlc->ostarted = 0;
+		do_gettimeofday(&(mlc->instart));
+		write_unlock_irqrestore(&(mlc->lock), flags);
+		nextidx = HILSEN_NEXT;
+		break;
+	case HILSE_CTS:
+		nextidx = mlc->cts(mlc) ? node->bad : node->good;
+		break;
+	default:
+		BUG();
+		nextidx = 0;
+		break;
+	}
+
+#ifdef HIL_MLC_DEBUG
+	if (nextidx == HILSEN_DOZE) doze++;
+#endif
+
+	while (nextidx & HILSEN_SCHED) {
+		struct timeval tv;
+
+		if (!sched_long) goto sched;
+
+		do_gettimeofday(&tv);
+		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		tv.tv_usec -= mlc->instart.tv_usec;
+		if (tv.tv_usec >= mlc->intimeout) goto sched;
+		tv.tv_usec = (mlc->intimeout - tv.tv_usec) * HZ / 1000000;
+		if (!tv.tv_usec) goto sched;
+		mod_timer(&hil_mlcs_kicker, jiffies + tv.tv_usec);
+		break;
+	sched:
+		tasklet_schedule(&hil_mlcs_tasklet);
+		break;
+	} 
+	if (nextidx & HILSEN_DOWN) mlc->seidx += nextidx & HILSEN_MASK;
+	else if (nextidx & HILSEN_UP) mlc->seidx -= nextidx & HILSEN_MASK;
+	else mlc->seidx = nextidx & HILSEN_MASK;
+
+	if (nextidx & HILSEN_BREAK)	return 1;
+	return 0;
+}
+
+/******************** tasklet context functions **************************/
+static void hil_mlcs_process(unsigned long unused) {
+	struct list_head *tmp;
+
+	read_lock(&hil_mlcs_lock);
+	list_for_each(tmp, &hil_mlcs) {
+		struct hil_mlc *mlc = list_entry(tmp, hil_mlc, list);
+		while (hilse_donode(mlc) == 0) {
+#ifdef HIL_MLC_DEBUG
+		  if (mlc->seidx != 41 && 
+		      mlc->seidx != 42 && 
+		      mlc->seidx != 43) 
+		    printk(KERN_DEBUG PREFIX " + ");
+#endif
+		};
+	}
+	read_unlock(&hil_mlcs_lock);
+}
+
+/************************* Keepalive timer task *********************/
+
+void hil_mlcs_timer (unsigned long data) {
+	hil_mlcs_probe = 1;
+	tasklet_schedule(&hil_mlcs_tasklet);
+	/* Re-insert the periodic task. */
+	if (!timer_pending(&hil_mlcs_kicker))
+		mod_timer(&hil_mlcs_kicker, jiffies + HZ);
+}
+
+/******************** user/kernel context functions **********************/
+
+static int hil_mlc_serio_write(struct serio *serio, unsigned char c) {
+	struct hil_mlc_serio_map *map;
+	struct hil_mlc *mlc;
+	struct serio_driver *drv;
+	uint8_t *idx, *last;
+
+	map = serio->port_data;
+	if (map == NULL) {
+		BUG();
+		return -EIO;
+	}
+	mlc = map->mlc;
+	if (mlc == NULL) {
+		BUG();
+		return -EIO;
+	}
+	mlc->serio_opacket[map->didx] |= 
+		((hil_packet)c) << (8 * (3 - mlc->serio_oidx[map->didx]));
+
+	if (mlc->serio_oidx[map->didx] >= 3) {
+		/* for now only commands */
+		if (!(mlc->serio_opacket[map->didx] & HIL_PKT_CMD)) 
+			return -EIO;
+		switch (mlc->serio_opacket[map->didx] & HIL_PKT_DATA_MASK) {
+		case HIL_CMD_IDD:
+			idx = mlc->di[map->didx].idd;
+			goto emu;
+		case HIL_CMD_RSC:
+			idx = mlc->di[map->didx].rsc;
+			goto emu;
+		case HIL_CMD_EXD:
+			idx = mlc->di[map->didx].exd;
+			goto emu;
+		case HIL_CMD_RNM:
+			idx = mlc->di[map->didx].rnm;
+			goto emu;
+		default:
+			break;
+		}
+		mlc->serio_oidx[map->didx] = 0;
+		mlc->serio_opacket[map->didx] = 0;
+	}
+
+	mlc->serio_oidx[map->didx]++;
+	return -EIO;
+ emu:
+	drv = serio->drv;
+	if (drv == NULL) {
+		BUG();
+		return -EIO;
+	}
+	last = idx + 15;
+	while ((last != idx) && (*last == 0)) last--;
+
+	while (idx != last) {
+		drv->interrupt(serio, 0, 0, NULL);
+		drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+		drv->interrupt(serio, 0, 0, NULL);
+		drv->interrupt(serio, *idx, 0, NULL);
+		idx++;
+	}
+	drv->interrupt(serio, 0, 0, NULL);
+	drv->interrupt(serio, HIL_ERR_INT >> 16, 0, NULL);
+	drv->interrupt(serio, HIL_PKT_CMD >> 8, 0, NULL);
+	drv->interrupt(serio, *idx, 0, NULL);
+	
+	mlc->serio_oidx[map->didx] = 0;
+	mlc->serio_opacket[map->didx] = 0;
+
+	return 0;
+}
+
+static int hil_mlc_serio_open(struct serio *serio) {
+	struct hil_mlc_serio_map *map;
+	struct hil_mlc *mlc;
+
+	if (serio->private != NULL) return -EBUSY;
+
+	map = serio->port_data;
+	if (map == NULL) {
+		BUG();
+		return -ENODEV;
+	}
+	mlc = map->mlc;
+	if (mlc == NULL) {
+		BUG();
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void hil_mlc_serio_close(struct serio *serio) {
+	struct hil_mlc_serio_map *map;
+	struct hil_mlc *mlc;
+
+	map = serio->port_data;
+	if (map == NULL) {
+		BUG();
+		return;
+	}
+	mlc = map->mlc;
+	if (mlc == NULL) {
+		BUG();
+		return;
+	}
+
+	serio->private = NULL;
+	serio->drv = NULL;
+	/* TODO wake up interruptable */
+}
+
+int hil_mlc_register(hil_mlc *mlc) {
+	int i;
+        unsigned long flags;
+
+	if (mlc == NULL) {
+		return -EINVAL;
+	}
+
+	mlc->istarted = 0;
+        mlc->ostarted = 0;
+
+        mlc->lock = RW_LOCK_UNLOCKED;
+        init_MUTEX(&(mlc->osem));
+
+        init_MUTEX(&(mlc->isem));
+        mlc->icount = -1;
+        mlc->imatch = 0;
+
+	mlc->opercnt = 0;
+
+        init_MUTEX_LOCKED(&(mlc->csem));
+
+	hil_mlc_clear_di_scratch(mlc);
+	hil_mlc_clear_di_map(mlc, 0);
+	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
+		struct serio *mlc_serio;
+		hil_mlc_copy_di_scratch(mlc, i);
+		mlc_serio = kmalloc(sizeof(*mlc_serio), GFP_KERNEL);
+		mlc->serio[i] = mlc_serio;
+		memset(mlc_serio, 0, sizeof(*mlc_serio));
+		mlc_serio->type			= SERIO_HIL | SERIO_HIL_MLC;
+		mlc_serio->write		= hil_mlc_serio_write;
+		mlc_serio->open			= hil_mlc_serio_open;
+		mlc_serio->close		= hil_mlc_serio_close;
+		mlc_serio->port_data		= &(mlc->serio_map[i]);
+		mlc->serio_map[i].mlc		= mlc;
+		mlc->serio_map[i].didx		= i;
+		mlc->serio_map[i].di_revmap	= -1;
+		mlc->serio_opacket[i]		= 0;
+		mlc->serio_oidx[i]		= 0;
+		serio_register_port(mlc_serio);
+	}
+
+	mlc->tasklet = &hil_mlcs_tasklet;
+
+	write_lock_irqsave(&hil_mlcs_lock, flags);
+	list_add_tail(&mlc->list, &hil_mlcs);
+	mlc->seidx = HILSEN_START;
+	write_unlock_irqrestore(&hil_mlcs_lock, flags);
+
+	tasklet_schedule(&hil_mlcs_tasklet);
+	return 0;
+}
+
+int hil_mlc_unregister(hil_mlc *mlc) {
+	struct list_head *tmp;
+        unsigned long flags;
+	int i;
+
+	if (mlc == NULL)
+		return -EINVAL;
+
+	write_lock_irqsave(&hil_mlcs_lock, flags);
+	list_for_each(tmp, &hil_mlcs) {
+		if (list_entry(tmp, hil_mlc, list) == mlc)
+			goto found;
+	}
+
+	/* not found in list */
+	write_unlock_irqrestore(&hil_mlcs_lock, flags);
+	tasklet_schedule(&hil_mlcs_tasklet);
+	return -ENODEV;
+
+ found:
+	list_del(tmp);
+        write_unlock_irqrestore(&hil_mlcs_lock, flags);
+
+	for (i = 0; i < HIL_MLC_DEVMEM; i++) {
+		serio_unregister_port(mlc->serio[i]);
+		mlc->serio[i] = NULL;
+	}
+
+	tasklet_schedule(&hil_mlcs_tasklet);
+	return 0;
+}
+
+/**************************** Module interface *************************/
+
+static int __init hil_mlc_init(void)
+{
+	init_timer(&hil_mlcs_kicker);
+	hil_mlcs_kicker.expires = jiffies + HZ;
+	hil_mlcs_kicker.function = &hil_mlcs_timer;
+	add_timer(&hil_mlcs_kicker);
+
+	tasklet_enable(&hil_mlcs_tasklet);
+
+	return 0;
+}
+                
+static void __exit hil_mlc_exit(void)
+{
+	del_timer(&hil_mlcs_kicker);
+
+	tasklet_disable(&hil_mlcs_tasklet);
+	tasklet_kill(&hil_mlcs_tasklet);
+}
+                        
+module_init(hil_mlc_init);
+module_exit(hil_mlc_exit);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/serio/hp_sdc.c parisc-2.6-bk/drivers/input/serio/hp_sdc.c
--- linux-2.6.10-rc1-bk13/drivers/input/serio/hp_sdc.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/drivers/input/serio/hp_sdc.c	Wed Nov  3 06:12:03 2004
@@ -0,0 +1,1055 @@
+/*
+ * HP i8042-based System Device Controller driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ * Helge Deller's original hilkbd.c port for PA-RISC.
+ *
+ *
+ * Driver theory of operation:
+ *
+ * hp_sdc_put does all writing to the SDC.  ISR can run on a different 
+ * CPU than hp_sdc_put, but only one CPU runs hp_sdc_put at a time 
+ * (it cannot really benefit from SMP anyway.)  A tasket fit this perfectly.
+ *
+ * All data coming back from the SDC is sent via interrupt and can be read 
+ * fully in the ISR, so there are no latency/throughput problems there.  
+ * The problem is with output, due to the slow clock speed of the SDC 
+ * compared to the CPU.  This should not be too horrible most of the time, 
+ * but if used with HIL devices that support the multibyte transfer command, 
+ * keeping outbound throughput flowing at the 6500KBps that the HIL is 
+ * capable of is more than can be done at HZ=100.
+ *
+ * Busy polling for IBF clear wastes CPU cycles and bus cycles.  hp_sdc.ibf 
+ * is set to 0 when the IBF flag in the status register has cleared.  ISR 
+ * may do this, and may also access the parts of queued transactions related 
+ * to reading data back from the SDC, but otherwise will not touch the 
+ * hp_sdc state. Whenever a register is written hp_sdc.ibf is set to 1.
+ *
+ * The i8042 write index and the values in the 4-byte input buffer
+ * starting at 0x70 are kept track of in hp_sdc.wi, and .r7[], respectively,
+ * to minimize the amount of IO needed to the SDC.  However these values 
+ * do not need to be locked since they are only ever accessed by hp_sdc_put.
+ *
+ * A timer task schedules the tasklet once per second just to make
+ * sure it doesn't freeze up and to allow for bad reads to time out.
+ */
+
+#include <linux/hp_sdc.h>
+#include <linux/sched.h>
+#include <linux/errno.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/ioport.h>
+#include <linux/time.h>
+#include <linux/slab.h>
+#include <linux/hil.h>
+#include <asm/io.h>
+#include <asm/system.h>
+
+/* Machine-specific abstraction */
+
+#if defined(__hppa__)
+# include <asm/parisc-device.h>
+# define sdc_readb(p)		gsc_readb(p)
+# define sdc_writeb(v,p)	gsc_writeb((v),(p))
+#elif defined(__mc68000__)
+# include <asm/uaccess.h>
+# define sdc_readb(p)		in_8(p)
+# define sdc_writeb(v,p)	out_8((p),(v))
+#else
+# error "HIL is not supported on this platform"
+#endif
+
+#define PREFIX "HP SDC: "
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("HP i8042-based SDC Driver");
+MODULE_LICENSE("Dual BSD/GPL");
+
+EXPORT_SYMBOL(hp_sdc_request_timer_irq);
+EXPORT_SYMBOL(hp_sdc_request_hil_irq);
+EXPORT_SYMBOL(hp_sdc_request_cooked_irq);
+
+EXPORT_SYMBOL(hp_sdc_release_timer_irq);
+EXPORT_SYMBOL(hp_sdc_release_hil_irq);
+EXPORT_SYMBOL(hp_sdc_release_cooked_irq);
+
+EXPORT_SYMBOL(hp_sdc_enqueue_transaction);
+EXPORT_SYMBOL(hp_sdc_dequeue_transaction);
+
+static hp_i8042_sdc	hp_sdc;	/* All driver state is kept in here. */
+
+/*************** primitives for use in any context *********************/
+static inline uint8_t hp_sdc_status_in8 (void) {
+	uint8_t status;
+	unsigned long flags;
+
+	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+	status = sdc_readb(hp_sdc.status_io);
+	if (!(status & HP_SDC_STATUS_IBF)) hp_sdc.ibf = 0;
+	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+
+	return status;
+}
+
+static inline uint8_t hp_sdc_data_in8 (void) {
+	return sdc_readb(hp_sdc.data_io); 
+}
+
+static inline void hp_sdc_status_out8 (uint8_t val) {
+	unsigned long flags;
+
+	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+	hp_sdc.ibf = 1;
+	if ((val & 0xf0) == 0xe0) hp_sdc.wi = 0xff;
+	sdc_writeb(val, hp_sdc.status_io);
+	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+}
+
+static inline void hp_sdc_data_out8 (uint8_t val) {
+	unsigned long flags;
+
+	write_lock_irqsave(&hp_sdc.ibf_lock, flags);
+	hp_sdc.ibf = 1;
+	sdc_writeb(val, hp_sdc.data_io);
+	write_unlock_irqrestore(&hp_sdc.ibf_lock, flags);
+}
+
+/*	Care must be taken to only invoke hp_sdc_spin_ibf when 
+ *	absolutely needed, or in rarely invoked subroutines.  
+ *	Not only does it waste CPU cycles, it also wastes bus cycles. 
+ */
+static inline void hp_sdc_spin_ibf(void) {
+	unsigned long flags;
+	rwlock_t *lock;
+
+	lock = &hp_sdc.ibf_lock;
+
+	read_lock_irqsave(lock, flags);
+	if (!hp_sdc.ibf) {
+		read_unlock_irqrestore(lock, flags);
+		return;
+	}
+	read_unlock(lock);
+	write_lock(lock);
+	while (sdc_readb(hp_sdc.status_io) & HP_SDC_STATUS_IBF) {};
+	hp_sdc.ibf = 0;
+	write_unlock_irqrestore(lock, flags);
+}
+
+
+/************************ Interrupt context functions ************************/
+static void hp_sdc_take (int irq, void *dev_id, uint8_t status, uint8_t data) {
+	hp_sdc_transaction *curr;
+
+	read_lock(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr < 0) {
+	  	read_unlock(&hp_sdc.rtq_lock);
+		return;
+	}
+	curr = hp_sdc.tq[hp_sdc.rcurr];
+	read_unlock(&hp_sdc.rtq_lock);
+
+	curr->seq[curr->idx++] = status;
+	curr->seq[curr->idx++] = data;
+	hp_sdc.rqty -= 2;
+	do_gettimeofday(&hp_sdc.rtv);
+
+	if (hp_sdc.rqty <= 0) {
+		/* All data has been gathered. */
+		if(curr->seq[curr->actidx] & HP_SDC_ACT_SEMAPHORE) {
+			if (curr->act.semaphore) up(curr->act.semaphore);
+		}
+		if(curr->seq[curr->actidx] & HP_SDC_ACT_CALLBACK) {
+			if (curr->act.irqhook)
+				curr->act.irqhook(irq, dev_id, status, data);
+		}
+		curr->actidx = curr->idx;
+		curr->idx++;
+		/* Return control of this transaction */
+		write_lock(&hp_sdc.rtq_lock);
+		hp_sdc.rcurr = -1; 
+		hp_sdc.rqty = 0;
+		write_unlock(&hp_sdc.rtq_lock);
+		tasklet_schedule(&hp_sdc.task);
+	}
+}
+
+static irqreturn_t hp_sdc_isr(int irq, void *dev_id, struct pt_regs * regs) {
+	uint8_t status, data;
+
+	status = hp_sdc_status_in8();
+	/* Read data unconditionally to advance i8042. */
+	data =   hp_sdc_data_in8();
+
+	/* For now we are ignoring these until we get the SDC to behave. */
+	if (((status & 0xf1) == 0x51) && data == 0x82) {
+	  return IRQ_HANDLED;
+	}
+
+	switch(status & HP_SDC_STATUS_IRQMASK) {
+	      case 0: /* This case is not documented. */
+		break;
+	      case HP_SDC_STATUS_USERTIMER:
+	      case HP_SDC_STATUS_PERIODIC:
+	      case HP_SDC_STATUS_TIMER:
+		read_lock(&hp_sdc.hook_lock);
+	      	if (hp_sdc.timer != NULL)
+			hp_sdc.timer(irq, dev_id, status, data);
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	      case HP_SDC_STATUS_REG:
+		hp_sdc_take(irq, dev_id, status, data);
+		break;
+	      case HP_SDC_STATUS_HILCMD:
+	      case HP_SDC_STATUS_HILDATA:
+		read_lock(&hp_sdc.hook_lock);
+		if (hp_sdc.hil != NULL)
+			hp_sdc.hil(irq, dev_id, status, data);
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	      case HP_SDC_STATUS_PUP:
+		read_lock(&hp_sdc.hook_lock);
+		if (hp_sdc.pup != NULL)
+			hp_sdc.pup(irq, dev_id, status, data);
+		else printk(KERN_INFO PREFIX "HP SDC reports successful PUP.\n");
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	      default:
+		read_lock(&hp_sdc.hook_lock);
+		if (hp_sdc.cooked != NULL)
+			hp_sdc.cooked(irq, dev_id, status, data);
+		read_unlock(&hp_sdc.hook_lock);
+		break;
+	}
+	return IRQ_HANDLED;
+}
+
+
+static irqreturn_t hp_sdc_nmisr(int irq, void *dev_id, struct pt_regs * regs) {
+	int status;
+	
+	status = hp_sdc_status_in8();
+	printk(KERN_WARNING PREFIX "NMI !\n");
+
+#if 0	
+	if (status & HP_SDC_NMISTATUS_FHS) {
+		read_lock(&hp_sdc.hook_lock);
+	      	if (hp_sdc.timer != NULL)
+			hp_sdc.timer(irq, dev_id, status, 0);
+		read_unlock(&hp_sdc.hook_lock);
+	}
+	else {
+		/* TODO: pass this on to the HIL handler, or do SAK here? */
+		printk(KERN_WARNING PREFIX "HIL NMI\n");
+	}
+#endif
+	return IRQ_HANDLED;
+}
+
+
+/***************** Kernel (tasklet) context functions ****************/
+
+unsigned long hp_sdc_put(void);
+
+static void hp_sdc_tasklet(unsigned long foo) {
+
+	write_lock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr >= 0) {
+		struct timeval tv;
+		do_gettimeofday(&tv);
+		if (tv.tv_sec > hp_sdc.rtv.tv_sec) tv.tv_usec += 1000000;
+		if (tv.tv_usec - hp_sdc.rtv.tv_usec > HP_SDC_MAX_REG_DELAY) {
+			hp_sdc_transaction *curr;
+			uint8_t tmp;
+
+			curr = hp_sdc.tq[hp_sdc.rcurr];
+			/* If this turns out to be a normal failure mode
+			 * we'll need to figure out a way to communicate
+			 * it back to the application. and be less verbose.
+			 */
+			printk(KERN_WARNING PREFIX "read timeout (%ius)!\n",
+			       tv.tv_usec - hp_sdc.rtv.tv_usec);
+			curr->idx += hp_sdc.rqty;
+			hp_sdc.rqty = 0;
+			tmp = curr->seq[curr->actidx];
+			curr->seq[curr->actidx] |= HP_SDC_ACT_DEAD;
+			if(tmp & HP_SDC_ACT_SEMAPHORE) {
+				if (curr->act.semaphore) 
+					up(curr->act.semaphore);
+			}
+			if(tmp & HP_SDC_ACT_CALLBACK) {
+				/* Note this means that irqhooks may be called
+				 * in tasklet/bh context.
+				 */
+				if (curr->act.irqhook) 
+					curr->act.irqhook(0, 0, 0, 0);
+			}
+			curr->actidx = curr->idx;
+			curr->idx++;
+			hp_sdc.rcurr = -1; 
+		}
+	}
+	write_unlock_irq(&hp_sdc.rtq_lock);
+	hp_sdc_put();
+}
+
+unsigned long hp_sdc_put(void) {
+	hp_sdc_transaction *curr;
+	uint8_t act;
+	int idx, curridx;
+
+	int limit = 0;
+
+	write_lock(&hp_sdc.lock);
+
+	/* If i8042 buffers are full, we cannot do anything that
+	   requires output, so we skip to the administrativa. */
+	if (hp_sdc.ibf) {
+		hp_sdc_status_in8();
+		if (hp_sdc.ibf) goto finish;
+	}
+
+ anew:
+	/* See if we are in the middle of a sequence. */
+	if (hp_sdc.wcurr < 0) hp_sdc.wcurr = 0;
+	read_lock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr == hp_sdc.wcurr) hp_sdc.wcurr++;
+	read_unlock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+	curridx = hp_sdc.wcurr;
+
+	if (hp_sdc.tq[curridx] != NULL) goto start;
+
+	while (++curridx != hp_sdc.wcurr) {
+		if (curridx >= HP_SDC_QUEUE_LEN) {
+			curridx = -1; /* Wrap to top */
+			continue;
+		}
+		read_lock_irq(&hp_sdc.rtq_lock);
+		if (hp_sdc.rcurr == curridx) {
+			read_unlock_irq(&hp_sdc.rtq_lock);
+			continue;
+		}
+		read_unlock_irq(&hp_sdc.rtq_lock);
+		if (hp_sdc.tq[curridx] != NULL) break; /* Found one. */
+	}
+	if (curridx == hp_sdc.wcurr) { /* There's nothing queued to do. */
+		curridx = -1;
+	}
+	hp_sdc.wcurr = curridx;
+
+ start:
+
+	/* Check to see if the interrupt mask needs to be set. */
+	if (hp_sdc.set_im) {
+		hp_sdc_status_out8(hp_sdc.im | HP_SDC_CMD_SET_IM);
+		hp_sdc.set_im = 0;
+		goto finish;
+	}
+
+	if (hp_sdc.wcurr == -1) goto done;
+
+	curr = hp_sdc.tq[curridx];
+	idx = curr->actidx;
+
+	if (curr->actidx >= curr->endidx) {
+		hp_sdc.tq[curridx] = NULL;
+		/* Interleave outbound data between the transactions. */
+		hp_sdc.wcurr++;
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+		goto finish;	
+	}
+
+	act = curr->seq[idx];
+	idx++;
+
+	if (curr->idx >= curr->endidx) {
+		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		hp_sdc.tq[curridx] = NULL;
+		/* Interleave outbound data between the transactions. */
+		hp_sdc.wcurr++;
+		if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+		goto finish;	
+	}
+
+	while (act & HP_SDC_ACT_PRECMD) {
+		if (curr->idx != idx) {
+			idx++;
+			act &= ~HP_SDC_ACT_PRECMD;
+			break;
+		}
+		hp_sdc_status_out8(curr->seq[idx]);
+		curr->idx++;
+		/* act finished? */
+		if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_PRECMD)
+		  goto actdone;
+		/* skip quantity field if data-out sequence follows. */
+		if (act & HP_SDC_ACT_DATAOUT) curr->idx++;
+		goto finish;
+	}
+	if (act & HP_SDC_ACT_DATAOUT) {
+		int qty;
+
+		qty = curr->seq[idx];
+		idx++;
+		if (curr->idx - idx < qty) {
+			hp_sdc_data_out8(curr->seq[curr->idx]);
+			curr->idx++;
+			/* act finished? */
+			if ((curr->idx - idx >= qty) && 
+			    ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAOUT))
+				goto actdone;
+			goto finish;
+		}
+		idx += qty;
+		act &= ~HP_SDC_ACT_DATAOUT;
+	}
+	else while (act & HP_SDC_ACT_DATAREG) {
+		int mask;
+		uint8_t w7[4];
+
+		mask = curr->seq[idx];
+		if (idx != curr->idx) {
+			idx++;
+			idx += !!(mask & 1);
+			idx += !!(mask & 2);
+			idx += !!(mask & 4);
+			idx += !!(mask & 8);
+			act &= ~HP_SDC_ACT_DATAREG;
+			break;
+		}
+		
+		w7[0] = (mask & 1) ? curr->seq[++idx] : hp_sdc.r7[0];
+		w7[1] = (mask & 2) ? curr->seq[++idx] : hp_sdc.r7[1];
+		w7[2] = (mask & 4) ? curr->seq[++idx] : hp_sdc.r7[2];
+		w7[3] = (mask & 8) ? curr->seq[++idx] : hp_sdc.r7[3];
+		
+		if (hp_sdc.wi > 0x73 || hp_sdc.wi < 0x70 ||
+		        w7[hp_sdc.wi-0x70] == hp_sdc.r7[hp_sdc.wi-0x70]) {
+			int i = 0;
+
+			/* Need to point the write index register */	
+			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			if (i < 4) {
+				hp_sdc_status_out8(HP_SDC_CMD_SET_D0 + i);
+				hp_sdc.wi = 0x70 + i;
+				goto finish;
+			}
+			idx++;
+			if ((act & HP_SDC_ACT_DURING) == HP_SDC_ACT_DATAREG)
+				goto actdone;
+			curr->idx = idx;
+			act &= ~HP_SDC_ACT_DATAREG;
+			break;
+		}
+
+		hp_sdc_data_out8(w7[hp_sdc.wi - 0x70]);
+		hp_sdc.r7[hp_sdc.wi - 0x70] = w7[hp_sdc.wi - 0x70];
+		hp_sdc.wi++; /* write index register autoincrements */
+		{
+			int i = 0;
+
+			while ((i < 4) && w7[i] == hp_sdc.r7[i]) i++;
+			if (i >= 4) {
+				curr->idx = idx + 1;
+				if ((act & HP_SDC_ACT_DURING) == 
+				    HP_SDC_ACT_DATAREG)
+				        goto actdone;
+			}
+		}
+		goto finish;
+	}
+	/* We don't go any further in the command if there is a pending read,
+	   because we don't want interleaved results. */
+	read_lock_irq(&hp_sdc.rtq_lock);
+	if (hp_sdc.rcurr >= 0) {
+		read_unlock_irq(&hp_sdc.rtq_lock);
+		goto finish;
+	}
+	read_unlock_irq(&hp_sdc.rtq_lock);
+
+
+	if (act & HP_SDC_ACT_POSTCMD) {
+	  	uint8_t postcmd;
+
+		/* curr->idx should == idx at this point. */
+		postcmd = curr->seq[idx];
+		curr->idx++;
+		if (act & HP_SDC_ACT_DATAIN) {
+
+			/* Start a new read */
+	  		hp_sdc.rqty = curr->seq[curr->idx];
+			do_gettimeofday(&hp_sdc.rtv);
+			curr->idx++;
+			/* Still need to lock here in case of spurious irq. */
+			write_lock_irq(&hp_sdc.rtq_lock);
+			hp_sdc.rcurr = curridx; 
+			write_unlock_irq(&hp_sdc.rtq_lock);
+			hp_sdc_status_out8(postcmd);
+			goto finish;
+		}
+		hp_sdc_status_out8(postcmd);
+		goto actdone;
+	}
+
+actdone:
+	if (act & HP_SDC_ACT_SEMAPHORE) {
+		up(curr->act.semaphore);
+	}
+	else if (act & HP_SDC_ACT_CALLBACK) {
+		curr->act.irqhook(0,0,0,0);
+	}
+	if (curr->idx >= curr->endidx) { /* This transaction is over. */
+		if (act & HP_SDC_ACT_DEALLOC) kfree(curr);
+		hp_sdc.tq[curridx] = NULL;
+	}
+	else {
+		curr->actidx = idx + 1;
+		curr->idx = idx + 2;
+	}
+	/* Interleave outbound data between the transactions. */
+	hp_sdc.wcurr++;
+	if (hp_sdc.wcurr >= HP_SDC_QUEUE_LEN) hp_sdc.wcurr = 0;
+
+ finish:
+	/* If by some quirk IBF has cleared and our ISR has run to 
+	   see that that has happened, do it all again. */
+	if (!hp_sdc.ibf && limit++ < 20) goto anew;
+
+ done:
+	if (hp_sdc.wcurr >= 0) tasklet_schedule(&hp_sdc.task);
+	write_unlock(&hp_sdc.lock);
+	return 0;
+}
+
+/******* Functions called in either user or kernel context ****/
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this) {
+	unsigned long flags;
+	int i;
+
+	if (this == NULL) {
+		tasklet_schedule(&hp_sdc.task);
+		return -EINVAL;
+	};
+
+	write_lock_irqsave(&hp_sdc.lock, flags);
+
+	/* Can't have same transaction on queue twice */
+	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this) goto fail;
+
+	this->actidx = 0;
+	this->idx = 1;
+
+	/* Search for empty slot */
+	for (i=0; i < HP_SDC_QUEUE_LEN; i++) {
+		if (hp_sdc.tq[i] == NULL) {
+			hp_sdc.tq[i] = this;
+			write_unlock_irqrestore(&hp_sdc.lock, flags);
+			tasklet_schedule(&hp_sdc.task);
+			return 0;
+		}
+	}
+	write_unlock_irqrestore(&hp_sdc.lock, flags);
+	printk(KERN_WARNING PREFIX "No free slot to add transaction.\n");
+	return -EBUSY;
+
+ fail:
+	write_unlock_irqrestore(&hp_sdc.lock,flags);
+	printk(KERN_WARNING PREFIX "Transaction add failed: transaction already queued?\n");
+	return -EINVAL;
+}
+
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this) {
+	unsigned long flags;
+	int i;
+
+	write_lock_irqsave(&hp_sdc.lock, flags);
+
+	/* TODO: don't remove it if it's not done. */
+
+	for (i=0; i < HP_SDC_QUEUE_LEN; i++)
+		if (hp_sdc.tq[i] == this) hp_sdc.tq[i] = NULL;
+
+	write_unlock_irqrestore(&hp_sdc.lock, flags);
+	return 0;
+}
+
+
+
+/********************** User context functions **************************/
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback) {
+
+	if (callback == NULL || hp_sdc.dev == NULL) {
+		return -EINVAL;
+	}
+	write_lock_irq(&hp_sdc.hook_lock);
+	if (hp_sdc.timer != NULL) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EBUSY;
+	}
+
+	hp_sdc.timer = callback;
+	/* Enable interrupts from the timers */
+	hp_sdc.im &= ~HP_SDC_IM_FH;
+        hp_sdc.im &= ~HP_SDC_IM_PT;
+	hp_sdc.im &= ~HP_SDC_IM_TIMERS;
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback) {
+
+	if (callback == NULL || hp_sdc.dev == NULL) {
+		return -EINVAL;
+	}
+	write_lock_irq(&hp_sdc.hook_lock);
+	if (hp_sdc.hil != NULL) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EBUSY;
+	}
+
+	hp_sdc.hil = callback;
+	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback) {
+
+	if (callback == NULL || hp_sdc.dev == NULL) {
+		return -EINVAL;
+	}
+	write_lock_irq(&hp_sdc.hook_lock);
+	if (hp_sdc.cooked != NULL) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EBUSY;
+	}
+
+	/* Enable interrupts from the HIL MLC */
+	hp_sdc.cooked = callback;
+	hp_sdc.im &= ~(HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback) {
+
+
+	write_lock_irq(&hp_sdc.hook_lock);
+	if ((callback != hp_sdc.timer) ||
+	    (hp_sdc.timer == NULL)) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EINVAL;
+	}
+
+	/* Disable interrupts from the timers */
+	hp_sdc.timer = NULL;
+	hp_sdc.im |= HP_SDC_IM_TIMERS;
+	hp_sdc.im |= HP_SDC_IM_FH;
+	hp_sdc.im |= HP_SDC_IM_PT;
+	hp_sdc.set_im = 1;
+	write_unlock_irq(&hp_sdc.hook_lock);
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback) {
+
+	write_lock_irq(&hp_sdc.hook_lock);
+	if ((callback != hp_sdc.hil) ||
+	    (hp_sdc.hil == NULL)) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EINVAL;
+	}
+
+	hp_sdc.hil = NULL;
+	/* Disable interrupts from HIL only if there is no cooked driver. */
+	if(hp_sdc.cooked == NULL) {
+		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+		hp_sdc.set_im = 1;
+	}
+	write_unlock_irq(&hp_sdc.hook_lock);
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback) {
+
+	write_lock_irq(&hp_sdc.hook_lock);
+	if ((callback != hp_sdc.cooked) ||
+	    (hp_sdc.cooked == NULL)) {
+		write_unlock_irq(&hp_sdc.hook_lock);
+		return -EINVAL;
+	}
+
+	hp_sdc.cooked = NULL;
+	/* Disable interrupts from HIL only if there is no raw HIL driver. */
+	if(hp_sdc.hil == NULL) {
+		hp_sdc.im |= (HP_SDC_IM_HIL | HP_SDC_IM_RESET);
+		hp_sdc.set_im = 1;
+	}
+	write_unlock_irq(&hp_sdc.hook_lock);
+	tasklet_schedule(&hp_sdc.task);
+
+	return 0;
+}
+
+/************************* Keepalive timer task *********************/
+
+void hp_sdc_kicker (unsigned long data) {
+	tasklet_schedule(&hp_sdc.task);
+	/* Re-insert the periodic task. */
+	mod_timer(&hp_sdc.kicker, jiffies + HZ);
+}
+
+/************************** Module Initialization ***************************/
+
+#if defined(__hppa__)
+
+static struct parisc_device_id hp_sdc_tbl[] = {
+	{
+		.hw_type =	HPHW_FIO, 
+		.hversion_rev =	HVERSION_REV_ANY_ID,
+		.hversion =	HVERSION_ANY_ID,
+		.sversion =	0x73, 
+	 },
+	{ 0, }
+};
+
+MODULE_DEVICE_TABLE(parisc, hp_sdc_tbl);
+
+static int __init hp_sdc_init_hppa(struct parisc_device *d);
+
+static struct parisc_driver hp_sdc_driver = {
+	.name =		"HP SDC",
+	.id_table =	hp_sdc_tbl,
+	.probe =	hp_sdc_init_hppa,
+};
+
+#endif /* __hppa__ */
+
+static int __init hp_sdc_init(void)
+{
+	int i;
+	char *errstr;
+	hp_sdc_transaction t_sync;
+	uint8_t ts_sync[6];
+	struct semaphore s_sync;
+
+  	hp_sdc.lock		= RW_LOCK_UNLOCKED;
+  	hp_sdc.ibf_lock		= RW_LOCK_UNLOCKED;
+  	hp_sdc.rtq_lock		= RW_LOCK_UNLOCKED;
+  	hp_sdc.hook_lock	= RW_LOCK_UNLOCKED;
+
+	hp_sdc.timer		= NULL;
+	hp_sdc.hil		= NULL;
+	hp_sdc.pup		= NULL;
+	hp_sdc.cooked		= NULL;
+	hp_sdc.im		= HP_SDC_IM_MASK;  /* Mask maskable irqs */
+	hp_sdc.set_im		= 1;
+	hp_sdc.wi		= 0xff;
+	hp_sdc.r7[0]		= 0xff;
+	hp_sdc.r7[1]		= 0xff;
+	hp_sdc.r7[2]		= 0xff;
+	hp_sdc.r7[3]		= 0xff;
+	hp_sdc.ibf		= 1;
+
+	for (i = 0; i < HP_SDC_QUEUE_LEN; i++) hp_sdc.tq[i] = NULL;
+	hp_sdc.wcurr		= -1;
+        hp_sdc.rcurr		= -1;
+	hp_sdc.rqty		= 0;
+
+	hp_sdc.dev_err = -ENODEV;
+
+	errstr = "IO not found for";
+	if (!hp_sdc.base_io) goto err0;
+
+	errstr = "IRQ not found for";
+	if (!hp_sdc.irq) goto err0;
+
+	hp_sdc.dev_err = -EBUSY;
+
+#if defined(__hppa__)
+	errstr = "IO not available for";
+        if (request_region(hp_sdc.data_io, 2, hp_sdc_driver.name)) goto err0;
+#endif	
+
+	errstr = "IRQ not available for";
+        if(request_irq(hp_sdc.irq, &hp_sdc_isr, 0, "HP SDC",
+		       (void *) hp_sdc.base_io)) goto err1;
+
+	errstr = "NMI not available for";
+	if (request_irq(hp_sdc.nmi, &hp_sdc_nmisr, 0, "HP SDC NMI", 
+			(void *) hp_sdc.base_io)) goto err2;
+
+	printk(KERN_INFO PREFIX "HP SDC at 0x%p, IRQ %d (NMI IRQ %d)\n", 
+	       (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
+
+	hp_sdc_status_in8();
+	hp_sdc_data_in8();
+
+	tasklet_init(&hp_sdc.task, hp_sdc_tasklet, 0);
+
+	/* Sync the output buffer registers, thus scheduling hp_sdc_tasklet. */
+	t_sync.actidx	= 0;
+	t_sync.idx	= 1;
+	t_sync.endidx	= 6;
+	t_sync.seq	= ts_sync;
+	ts_sync[0]	= HP_SDC_ACT_DATAREG | HP_SDC_ACT_SEMAPHORE;
+	ts_sync[1]	= 0x0f;
+	ts_sync[2] = ts_sync[3]	= ts_sync[4] = ts_sync[5] = 0;
+	t_sync.act.semaphore = &s_sync;
+	init_MUTEX_LOCKED(&s_sync);
+	hp_sdc_enqueue_transaction(&t_sync);
+	down(&s_sync); /* Wait for t_sync to complete */
+
+	/* Create the keepalive task */
+	init_timer(&hp_sdc.kicker);
+	hp_sdc.kicker.expires = jiffies + HZ;
+	hp_sdc.kicker.function = &hp_sdc_kicker;
+	add_timer(&hp_sdc.kicker);
+
+	hp_sdc.dev_err = 0;
+	return 0;
+ err2:
+	free_irq(hp_sdc.irq, NULL);
+ err1:
+	release_region(hp_sdc.data_io, 2);
+ err0:
+	printk(KERN_WARNING PREFIX ": %s SDC IO=0x%p IRQ=0x%x NMI=0x%x\n", 
+		errstr, (void *)hp_sdc.base_io, hp_sdc.irq, hp_sdc.nmi);
+	hp_sdc.dev = NULL;
+	return hp_sdc.dev_err;
+}
+
+#if defined(__hppa__)
+
+static int __init hp_sdc_init_hppa(struct parisc_device *d)
+{
+	if (!d) return 1;
+	if (hp_sdc.dev != NULL) return 1;	/* We only expect one SDC */
+
+	hp_sdc.dev		= d;
+	hp_sdc.irq		= d->irq;
+	/* TODO: Is NMI == IRQ - 1 all cases, or is there a way to query? */
+	hp_sdc.nmi		= d->irq - 1;
+	hp_sdc.base_io		= (unsigned long) d->hpa;
+	hp_sdc.data_io		= (unsigned long) d->hpa + 0x800;
+	hp_sdc.status_io	= (unsigned long) d->hpa + 0x801;
+
+	return hp_sdc_init();
+}
+
+#endif /* __hppa__ */
+
+#if !defined(__mc68000__) /* Link error on m68k! */
+static void __exit hp_sdc_exit(void)
+#else
+static void hp_sdc_exit(void)
+#endif
+{
+	write_lock_irq(&hp_sdc.lock);
+
+	/* Turn off all maskable "sub-function" irq's. */
+	hp_sdc_spin_ibf();
+	sdc_writeb(HP_SDC_CMD_SET_IM | HP_SDC_IM_MASK, hp_sdc.status_io);
+
+	/* Wait until we know this has been processed by the i8042 */
+	hp_sdc_spin_ibf();
+
+	free_irq(hp_sdc.nmi, NULL);
+	free_irq(hp_sdc.irq, NULL);
+	write_unlock_irq(&hp_sdc.lock);
+
+	del_timer(&hp_sdc.kicker);
+
+	tasklet_kill(&hp_sdc.task);
+
+/*        release_region(hp_sdc.data_io, 2); */
+
+#if defined(__hppa__)
+	if (unregister_parisc_driver(&hp_sdc_driver)) 
+		printk(KERN_WARNING PREFIX "Error unregistering HP SDC");
+#endif
+}
+
+static int __init hp_sdc_register(void)
+{
+	hp_sdc_transaction tq_init;
+	uint8_t tq_init_seq[5];
+	struct semaphore tq_init_sem;
+#if defined(__mc68000__)
+	mm_segment_t fs;
+	unsigned char i;
+#endif
+	
+	hp_sdc.dev = NULL;
+	hp_sdc.dev_err = 0;
+#if defined(__hppa__)
+	if (register_parisc_driver(&hp_sdc_driver)) {
+		printk(KERN_WARNING PREFIX "Error registering SDC with system bus tree.\n");
+		return -ENODEV;
+	}
+#elif defined(__mc68000__)
+	if (!MACH_IS_HP300)
+	    return -ENODEV;
+
+	hp_sdc.irq	 = 1;
+	hp_sdc.nmi	 = 7;
+	hp_sdc.base_io	 = (unsigned long) 0xf0428000;
+	hp_sdc.data_io	 = (unsigned long) hp_sdc.base_io + 1;
+	hp_sdc.status_io = (unsigned long) hp_sdc.base_io + 3;
+	fs = get_fs();
+	set_fs(KERNEL_DS);
+	if (!get_user(i, (unsigned char *)hp_sdc.data_io))
+		hp_sdc.dev = (void *)1;
+	set_fs(fs);
+	hp_sdc.dev_err   = hp_sdc_init();
+#endif
+	if (hp_sdc.dev == NULL) {
+		printk(KERN_WARNING PREFIX "No SDC found.\n");
+		return hp_sdc.dev_err;
+	}
+
+	init_MUTEX_LOCKED(&tq_init_sem);
+
+	tq_init.actidx		= 0;
+	tq_init.idx		= 1;
+	tq_init.endidx		= 5;
+	tq_init.seq		= tq_init_seq;
+	tq_init.act.semaphore	= &tq_init_sem;
+
+	tq_init_seq[0] = 
+	  HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+	tq_init_seq[1] = HP_SDC_CMD_READ_KCC;
+	tq_init_seq[2] = 1;
+	tq_init_seq[3] = 0;
+	tq_init_seq[4] = 0;
+
+	hp_sdc_enqueue_transaction(&tq_init);
+
+	down(&tq_init_sem);
+	up(&tq_init_sem);
+
+	if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
+		printk(KERN_WARNING PREFIX "Error reading config byte.\n");
+		hp_sdc_exit();
+		return -ENODEV;
+	}
+	hp_sdc.r11 = tq_init_seq[4];
+	if (hp_sdc.r11 & HP_SDC_CFG_NEW) {
+		char *str;
+		printk(KERN_INFO PREFIX "New style SDC\n");
+		tq_init_seq[1] = HP_SDC_CMD_READ_XTD;
+		tq_init.actidx		= 0;
+		tq_init.idx		= 1;
+		down(&tq_init_sem);
+		hp_sdc_enqueue_transaction(&tq_init);		
+		down(&tq_init_sem);
+		up(&tq_init_sem);
+		if ((tq_init_seq[0] & HP_SDC_ACT_DEAD) == HP_SDC_ACT_DEAD) {
+			printk(KERN_WARNING PREFIX "Error reading extended config byte.\n");
+			return -ENODEV;
+		}
+		hp_sdc.r7e = tq_init_seq[4];
+		HP_SDC_XTD_REV_STRINGS(hp_sdc.r7e & HP_SDC_XTD_REV, str)
+		printk(KERN_INFO PREFIX "Revision: %s\n", str);
+		if (hp_sdc.r7e & HP_SDC_XTD_BEEPER) {
+			printk(KERN_INFO PREFIX "TI SN76494 beeper present\n");
+		}
+		if (hp_sdc.r7e & HP_SDC_XTD_BBRTC) {
+			printk(KERN_INFO PREFIX "OKI MSM-58321 BBRTC present\n");
+		}
+		printk(KERN_INFO PREFIX "Spunking the self test register to force PUP "
+		       "on next firmware reset.\n");
+		tq_init_seq[0] = HP_SDC_ACT_PRECMD | 
+			HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
+		tq_init_seq[1] = HP_SDC_CMD_SET_STR;
+		tq_init_seq[2] = 1;
+		tq_init_seq[3] = 0;
+		tq_init.actidx		= 0;
+		tq_init.idx		= 1;
+		tq_init.endidx		= 4;
+		down(&tq_init_sem);
+		hp_sdc_enqueue_transaction(&tq_init);		
+		down(&tq_init_sem);
+		up(&tq_init_sem);
+	}
+	else {
+		printk(KERN_INFO PREFIX "Old style SDC (1820-%s).\n", 
+		       (hp_sdc.r11 & HP_SDC_CFG_REV) ? "3300" : "2564/3087");
+	}
+
+        return 0;
+}
+
+module_init(hp_sdc_register);
+module_exit(hp_sdc_exit);
+
+/* Timing notes:  These measurements taken on my 64MHz 7100-LC (715/64) 
+ *                                              cycles cycles-adj    time
+ * between two consecutive mfctl(16)'s:              4        n/a    63ns
+ * hp_sdc_spin_ibf when idle:                      119        115   1.7us
+ * gsc_writeb status register:                      83         79   1.2us
+ * IBF to clear after sending SET_IM:             6204       6006    93us
+ * IBF to clear after sending LOAD_RT:            4467       4352    68us  
+ * IBF to clear after sending two LOAD_RTs:      18974      18859   295us
+ * READ_T1, read status/data, IRQ, call handler: 35564        n/a   556us
+ * cmd to ~IBF READ_T1 2nd time right after:   5158403        n/a    81ms
+ * between IRQ received and ~IBF for above:    2578877        n/a    40ms
+ *
+ * Performance stats after a run of this module configuring HIL and
+ * receiving a few mouse events:
+ *
+ * status in8  282508 cycles 7128 calls
+ * status out8   8404 cycles  341 calls
+ * data out8     1734 cycles   78 calls
+ * isr         174324 cycles  617 calls (includes take)
+ * take          1241 cycles    2 calls
+ * put        1411504 cycles 6937 calls
+ * task       1655209 cycles 6937 calls (includes put)
+ *
+ */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/input/serio/hp_sdc_mlc.c parisc-2.6-bk/drivers/input/serio/hp_sdc_mlc.c
--- linux-2.6.10-rc1-bk13/drivers/input/serio/hp_sdc_mlc.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/drivers/input/serio/hp_sdc_mlc.c	Wed Nov  3 06:12:04 2004
@@ -0,0 +1,358 @@
+/*
+ * Access to HP-HIL MLC through HP System Device Controller.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ *      for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ *
+ */
+
+#include <linux/hil_mlc.h>
+#include <linux/hp_sdc.h>
+#include <linux/errno.h>
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/string.h>
+
+#define PREFIX "HP SDC MLC: "
+
+static hil_mlc hp_sdc_mlc;
+
+MODULE_AUTHOR("Brian S. Julin <bri@calyx.com>");
+MODULE_DESCRIPTION("Glue for onboard HIL MLC in HP-PARISC machines");
+MODULE_LICENSE("Dual BSD/GPL");
+
+struct hp_sdc_mlc_priv_s {
+	int emtestmode;
+	hp_sdc_transaction trans;
+	u8 tseq[16];
+	int got5x;
+} hp_sdc_mlc_priv;
+
+/************************* Interrupt context ******************************/
+static void hp_sdc_mlc_isr (int irq, void *dev_id, 
+			    uint8_t status, uint8_t data) {
+  	int idx;
+	hil_mlc *mlc = &hp_sdc_mlc;
+
+	write_lock(&(mlc->lock));
+	if (mlc->icount < 0) {
+		printk(KERN_WARNING PREFIX "HIL Overflow!\n");
+		up(&mlc->isem);
+		goto out;
+	}
+	idx = 15 - mlc->icount;
+	if ((status & HP_SDC_STATUS_IRQMASK) == HP_SDC_STATUS_HILDATA) {
+		mlc->ipacket[idx] |= data | HIL_ERR_INT;
+		mlc->icount--;
+		if (hp_sdc_mlc_priv.got5x) goto check;
+		if (!idx) goto check;
+		if ((mlc->ipacket[idx-1] & HIL_PKT_ADDR_MASK) !=
+		    (mlc->ipacket[idx] & HIL_PKT_ADDR_MASK)) {
+			mlc->ipacket[idx] &= ~HIL_PKT_ADDR_MASK;
+			mlc->ipacket[idx] |= (mlc->ipacket[idx-1] 
+						    & HIL_PKT_ADDR_MASK);
+		}
+		goto check;
+	}
+	/* We know status is 5X */
+	if (data & HP_SDC_HIL_ISERR) goto err;
+	mlc->ipacket[idx] = 
+		(data & HP_SDC_HIL_R1MASK) << HIL_PKT_ADDR_SHIFT;
+	hp_sdc_mlc_priv.got5x = 1;
+	goto out;
+
+ check:
+	hp_sdc_mlc_priv.got5x = 0;
+	if (mlc->imatch == 0) goto done;
+	if ((mlc->imatch == (HIL_ERR_INT | HIL_PKT_CMD | HIL_CMD_POL)) 
+	    && (mlc->ipacket[idx] == (mlc->imatch | idx))) goto done;
+	if (mlc->ipacket[idx] == mlc->imatch) goto done;
+	goto out;
+
+ err:				
+	printk(KERN_DEBUG PREFIX "err code %x\n", data);
+	switch (data) {
+	case HP_SDC_HIL_RC_DONE:
+		printk(KERN_WARNING PREFIX "Bastard SDC reconfigured loop!\n");
+		break;
+	case HP_SDC_HIL_ERR:
+		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_PERR | 
+		  HIL_ERR_FERR | HIL_ERR_FOF;
+		break;
+	case HP_SDC_HIL_TO:
+		mlc->ipacket[idx] |= HIL_ERR_INT | HIL_ERR_LERR;
+		break;
+	case HP_SDC_HIL_RC:
+		printk(KERN_WARNING PREFIX "Bastard SDC decided to reconfigure loop!\n");
+		break;
+	default:
+		printk(KERN_WARNING PREFIX "Unkown HIL Error status (%x)!\n", data);
+		break;
+	}
+	/* No more data will be coming due to an error. */
+ done:
+	tasklet_schedule(mlc->tasklet);
+	up(&(mlc->isem));
+ out:
+	write_unlock(&(mlc->lock));
+}
+
+
+/******************** Tasklet or userspace context functions ****************/
+
+static int hp_sdc_mlc_in (hil_mlc *mlc, suseconds_t timeout) {
+	unsigned long flags;
+	struct hp_sdc_mlc_priv_s *priv;
+	int rc = 2;
+
+	priv = mlc->priv;
+
+	write_lock_irqsave(&(mlc->lock), flags);
+
+	/* Try to down the semaphore */
+	if (down_trylock(&(mlc->isem))) {
+		struct timeval tv;
+		if (priv->emtestmode) {
+			mlc->ipacket[0] = 
+				HIL_ERR_INT | (mlc->opacket & 
+					       (HIL_PKT_CMD | 
+						HIL_PKT_ADDR_MASK | 
+						HIL_PKT_DATA_MASK));
+			mlc->icount = 14;
+			/* printk(KERN_DEBUG PREFIX ">[%x]\n", mlc->ipacket[0]); */
+			goto wasup;
+		}
+		do_gettimeofday(&tv);
+		tv.tv_usec += 1000000 * (tv.tv_sec - mlc->instart.tv_sec);
+		if (tv.tv_usec - mlc->instart.tv_usec > mlc->intimeout) {
+		  /*		  printk("!%i %i", 
+				  tv.tv_usec - mlc->instart.tv_usec, 
+				  mlc->intimeout);
+		  */
+			rc = 1;
+			up(&(mlc->isem));
+		}
+		goto done;
+	}
+ wasup:
+	up(&(mlc->isem));
+	rc = 0;
+	goto done;
+ done:
+	write_unlock_irqrestore(&(mlc->lock), flags);
+	return rc;
+}
+
+static int hp_sdc_mlc_cts (hil_mlc *mlc) {
+	struct hp_sdc_mlc_priv_s *priv;
+	unsigned long flags;
+
+	priv = mlc->priv;	
+
+	write_lock_irqsave(&(mlc->lock), flags);
+
+	/* Try to down the semaphores -- they should be up. */
+	if (down_trylock(&(mlc->isem))) {
+		BUG();
+		goto busy;
+	}
+	if (down_trylock(&(mlc->osem))) {
+	 	BUG();
+		up(&(mlc->isem));
+		goto busy;
+	}
+	up(&(mlc->isem));
+	up(&(mlc->osem));
+
+	if (down_trylock(&(mlc->csem))) {
+		if (priv->trans.act.semaphore != &(mlc->csem)) goto poll;
+		goto busy;
+	}
+	if (!(priv->tseq[4] & HP_SDC_USE_LOOP)) goto done;
+
+ poll:
+	priv->trans.act.semaphore = &(mlc->csem);
+	priv->trans.actidx = 0;
+	priv->trans.idx = 1;
+	priv->trans.endidx = 5;
+	priv->tseq[0] = 
+		HP_SDC_ACT_POSTCMD | HP_SDC_ACT_DATAIN | HP_SDC_ACT_SEMAPHORE;
+	priv->tseq[1] = HP_SDC_CMD_READ_USE;
+	priv->tseq[2] = 1;
+	priv->tseq[3] = 0;
+	priv->tseq[4] = 0;
+	hp_sdc_enqueue_transaction(&(priv->trans));
+ busy:
+	write_unlock_irqrestore(&(mlc->lock), flags);
+	return 1;
+ done:
+	priv->trans.act.semaphore = &(mlc->osem);
+	up(&(mlc->csem));
+	write_unlock_irqrestore(&(mlc->lock), flags);
+	return 0;
+}
+
+static void hp_sdc_mlc_out (hil_mlc *mlc) {
+	struct hp_sdc_mlc_priv_s *priv;
+	unsigned long flags;
+
+	priv = mlc->priv;
+
+	write_lock_irqsave(&(mlc->lock), flags);
+	
+	/* Try to down the semaphore -- it should be up. */
+	if (down_trylock(&(mlc->osem))) {
+	 	BUG();
+		goto done;
+	}
+
+	if (mlc->opacket & HIL_DO_ALTER_CTRL) goto do_control;
+
+ do_data:
+	if (priv->emtestmode) {
+		up(&(mlc->osem));
+		goto done;
+	}
+	/* Shouldn't be sending commands when loop may be busy */
+	if (down_trylock(&(mlc->csem))) {
+	 	BUG();
+		goto done;
+	}
+	up(&(mlc->csem));
+
+	priv->trans.actidx = 0;
+	priv->trans.idx = 1;
+	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.endidx = 6;
+	priv->tseq[0] = 
+		HP_SDC_ACT_DATAREG | HP_SDC_ACT_POSTCMD | HP_SDC_ACT_SEMAPHORE;
+	priv->tseq[1] = 0x7;
+	priv->tseq[2] = 
+		(mlc->opacket & 
+		 (HIL_PKT_ADDR_MASK | HIL_PKT_CMD))
+		   >> HIL_PKT_ADDR_SHIFT;
+	priv->tseq[3] = 
+		(mlc->opacket & HIL_PKT_DATA_MASK) 
+		  >> HIL_PKT_DATA_SHIFT;
+	priv->tseq[4] = 0;  /* No timeout */
+	if (priv->tseq[3] == HIL_CMD_DHR) priv->tseq[4] = 1;
+	priv->tseq[5] = HP_SDC_CMD_DO_HIL;
+	goto enqueue;
+
+ do_control:
+	priv->emtestmode = mlc->opacket & HIL_CTRL_TEST;
+	if ((mlc->opacket & (HIL_CTRL_APE | HIL_CTRL_IPF)) == HIL_CTRL_APE) {
+		BUG(); /* we cannot emulate this, it should not be used. */
+	}
+	if ((mlc->opacket & HIL_CTRL_ONLY) == HIL_CTRL_ONLY) goto control_only;
+	if (mlc->opacket & HIL_CTRL_APE) { 
+		BUG(); /* Should not send command/data after engaging APE */
+		goto done;
+	}
+	/* Disengaging APE this way would not be valid either since 
+	 * the loop must be allowed to idle.
+	 *
+	 * So, it works out that we really never actually send control 
+	 * and data when using SDC, we just send the data. 
+	 */
+	goto do_data;
+
+ control_only:
+	priv->trans.actidx = 0;
+	priv->trans.idx = 1;
+	priv->trans.act.semaphore = &(mlc->osem);
+	priv->trans.endidx = 4;
+	priv->tseq[0] = 
+	  HP_SDC_ACT_PRECMD | HP_SDC_ACT_DATAOUT | HP_SDC_ACT_SEMAPHORE;
+	priv->tseq[1] = HP_SDC_CMD_SET_LPC;
+	priv->tseq[2] = 1;
+	//	priv->tseq[3] = (mlc->ddc + 1) | HP_SDC_LPS_ACSUCC;
+	priv->tseq[3] = 0;
+	if (mlc->opacket & HIL_CTRL_APE) {
+		priv->tseq[3] |= HP_SDC_LPC_APE_IPF;
+		down_trylock(&(mlc->csem));
+	} 
+ enqueue:
+	hp_sdc_enqueue_transaction(&(priv->trans));
+ done:
+	write_unlock_irqrestore(&(mlc->lock), flags);
+}
+
+static int __init hp_sdc_mlc_init(void)
+{
+	hil_mlc *mlc = &hp_sdc_mlc;
+
+	printk(KERN_INFO PREFIX "Registering the System Domain Controller's HIL MLC.\n");
+
+	hp_sdc_mlc_priv.emtestmode = 0;
+	hp_sdc_mlc_priv.trans.seq = hp_sdc_mlc_priv.tseq;
+	hp_sdc_mlc_priv.trans.act.semaphore = &(mlc->osem);
+	hp_sdc_mlc_priv.got5x = 0;
+
+	mlc->cts		= &hp_sdc_mlc_cts;
+	mlc->in			= &hp_sdc_mlc_in;
+	mlc->out		= &hp_sdc_mlc_out;
+
+	if (hil_mlc_register(mlc)) {
+		printk(KERN_WARNING PREFIX "Failed to register MLC structure with hil_mlc\n");
+		goto err0;
+	}
+	mlc->priv		= &hp_sdc_mlc_priv;
+
+	if (hp_sdc_request_hil_irq(&hp_sdc_mlc_isr)) {
+		printk(KERN_WARNING PREFIX "Request for raw HIL ISR hook denied\n");
+		goto err1;
+	}
+	return 0;
+ err1:
+	if (hil_mlc_unregister(mlc)) {
+		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
+			"This is bad.  Could cause an oops.\n");
+	}
+ err0:
+	return -EBUSY;
+}
+
+static void __exit hp_sdc_mlc_exit(void)
+{
+	hil_mlc *mlc = &hp_sdc_mlc;
+	if (hp_sdc_release_hil_irq(&hp_sdc_mlc_isr)) {
+		printk(KERN_ERR PREFIX "Failed to release the raw HIL ISR hook.\n"
+			"This is bad.  Could cause an oops.\n");
+	}
+	if (hil_mlc_unregister(mlc)) {
+		printk(KERN_ERR PREFIX "Failed to unregister MLC structure with hil_mlc.\n"
+			"This is bad.  Could cause an oops.\n");
+	}
+}
+
+module_init(hp_sdc_mlc_init);
+module_exit(hp_sdc_mlc_exit);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/net/tulip/media.c parisc-2.6-bk/drivers/net/tulip/media.c
--- linux-2.6.10-rc1-bk13/drivers/net/tulip/media.c	Fri Oct 22 15:38:40 2004
+++ parisc-2.6-bk/drivers/net/tulip/media.c	Wed Nov  3 06:19:05 2004
@@ -43,8 +43,10 @@ static const unsigned char comet_miireg2
 
 /* MII transceiver control section.
    Read and write the MII registers using software-generated serial
-   MDIO protocol.  See the MII specifications or DP83840A data sheet
-   for details. */
+   MDIO protocol.
+   See IEEE 802.3-2002.pdf (Section 2, Chapter "22.2.4 Management functions")
+   or DP83840A data sheet for more details.
+   */
 
 int tulip_mdio_read(struct net_device *dev, int phy_id, int location)
 {
@@ -271,13 +273,29 @@ void tulip_select_media(struct net_devic
 				int reset_length = p[2 + init_length];
 				misc_info = (u16*)(reset_sequence + reset_length);
 				if (startup) {
+					int timeout = 10;	/* max 1 ms */
 					iowrite32(mtable->csr12dir | 0x100, ioaddr + CSR12);
 					for (i = 0; i < reset_length; i++)
 						iowrite32(reset_sequence[i], ioaddr + CSR12);
+
+					/* flush posted writes */
+					ioread32(ioaddr + CSR12);
+
+					/* Sect 3.10.3 in DP83840A.pdf (p39) */
+					udelay(500);
+
+					/* Section 4.2 in DP83840A.pdf (p43) */
+					/* and IEEE 802.3 "22.2.4.1.1 Reset" */
+					while (timeout-- &&
+						(tulip_mdio_read (dev, phy_num, MII_BMCR) & BMCR_RESET))
+						udelay(100);
 				}
 				for (i = 0; i < init_length; i++)
 					iowrite32(init_sequence[i], ioaddr + CSR12);
+
+				ioread32(ioaddr + CSR12);	/* flush posted writes */
 			}
+
 			tmp_info = get_u16(&misc_info[1]);
 			if (tmp_info)
 				tp->advertising[phy_num] = tmp_info | 1;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/parisc/asp.c parisc-2.6-bk/drivers/parisc/asp.c
--- linux-2.6.10-rc1-bk13/drivers/parisc/asp.c	Fri Oct 22 15:40:36 2004
+++ parisc-2.6-bk/drivers/parisc/asp.c	Wed Nov  3 06:19:06 2004
@@ -103,7 +103,7 @@ asp_init_chip(struct parisc_device *dev)
 
 	fixup_child_irqs(dev, asp->busdev_region->data.irqbase, asp_choose_irq);
 	/* Mongoose is a sibling of Asp, not a child... */
-	fixup_child_irqs(dev->parent, asp->busdev_region->data.irqbase,
+	fixup_child_irqs(parisc_parent(dev), asp->busdev_region->data.irqbase,
 			asp_choose_irq);
 
 	/* initialize the chassis LEDs */ 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/parisc/ccio-dma.c parisc-2.6-bk/drivers/parisc/ccio-dma.c
--- linux-2.6.10-rc1-bk13/drivers/parisc/ccio-dma.c	Fri Oct 22 15:38:39 2004
+++ parisc-2.6-bk/drivers/parisc/ccio-dma.c	Wed Nov  3 06:19:06 2004
@@ -1198,9 +1198,10 @@ void * ccio_get_iommu(const struct paris
  * to/from certain pages.  To avoid this happening, we mark these pages
  * as `used', and ensure that nothing will try to allocate from them.
  */
-void ccio_cujo20_fixup(struct parisc_device *dev, u32 iovp)
+void ccio_cujo20_fixup(struct parisc_device *cujo, u32 iovp)
 {
 	unsigned int idx;
+	struct parisc_device *dev = parisc_parent(cujo);
 	struct ioc *ioc = ccio_get_iommu(dev);
 	u8 *res_ptr;
 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/parisc/dino.c parisc-2.6-bk/drivers/parisc/dino.c
--- linux-2.6.10-rc1-bk13/drivers/parisc/dino.c	Wed Nov  3 07:57:06 2004
+++ parisc-2.6-bk/drivers/parisc/dino.c	Wed Nov  3 06:19:06 2004
@@ -563,7 +563,7 @@ dino_fixup_bus(struct pci_bus *bus)
         struct dino_device *dino_dev = DINO_DEV(parisc_walk_tree(bus->bridge));
 	int port_base = HBA_PORT_BASE(dino_dev->hba.hba_num);
 
-	DBG(KERN_WARNING "%s(0x%p) bus %d sysdata 0x%p\n",
+	DBG(KERN_WARNING "%s(0x%p) bus %d platform_data 0x%p\n",
 			__FUNCTION__, bus, bus->secondary, bus->bridge->platform_data);
 
 	/* Firmware doesn't set up card-mode dino, so we have to */
@@ -974,9 +974,9 @@ dino_driver_callback(struct parisc_devic
 #ifdef CONFIG_IOMMU_CCIO
 		printk(KERN_WARNING "Enabling Cujo 2.0 bug workaround\n");
 		if (dev->hpa == (unsigned long)CUJO_RAVEN_ADDR) {
-			ccio_cujo20_fixup(dev->parent, CUJO_RAVEN_BADPAGE);
+			ccio_cujo20_fixup(dev, CUJO_RAVEN_BADPAGE);
 		} else if (dev->hpa == (unsigned long)CUJO_FIREHAWK_ADDR) {
-			ccio_cujo20_fixup(dev->parent, CUJO_FIREHAWK_BADPAGE);
+			ccio_cujo20_fixup(dev, CUJO_FIREHAWK_BADPAGE);
 		} else {
 			printk("Don't recognise Cujo at address 0x%lx, not enabling workaround\n", dev->hpa);
 		}
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/parisc/lba_pci.c parisc-2.6-bk/drivers/parisc/lba_pci.c
--- linux-2.6.10-rc1-bk13/drivers/parisc/lba_pci.c	Wed Nov  3 07:57:06 2004
+++ parisc-2.6-bk/drivers/parisc/lba_pci.c	Wed Nov  3 06:27:32 2004
@@ -834,7 +834,7 @@ lba_fixup_bus(struct pci_bus *bus)
 	struct lba_device *ldev = LBA_DEV(parisc_walk_tree(bus->bridge));
 	int lba_portbase = HBA_PORT_BASE(ldev->hba.hba_num);
 
-	DBG("lba_fixup_bus(0x%p) bus %d sysdata 0x%p\n",
+	DBG("lba_fixup_bus(0x%p) bus %d platform_data 0x%p\n",
 		bus, bus->secondary, bus->bridge->platform_data);
 
 	/*
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/parisc/sba_iommu.c parisc-2.6-bk/drivers/parisc/sba_iommu.c
--- linux-2.6.10-rc1-bk13/drivers/parisc/sba_iommu.c	Wed Nov  3 05:57:46 2004
+++ parisc-2.6-bk/drivers/parisc/sba_iommu.c	Wed Nov  3 06:19:06 2004
@@ -1394,16 +1394,27 @@ sba_alloc_pdir(unsigned int pdir_size)
 	return (void *) pdir_base;
 }
 
-static void
-sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+/* setup Mercury or Elroy IBASE/IMASK registers. */
+static void setup_ibase_imask(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 {
         /* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
         extern void lba_set_iregs(struct parisc_device *, u32, u32);
+	struct device *dev;
 
+	list_for_each_entry(dev, &sba->dev.children, node) {
+		struct parisc_device *lba = to_parisc_device(dev);
+		int rope_num = (lba->hpa >> 13) & 0xf;
+		if (rope_num >> 3 == ioc_num)
+			lba_set_iregs(lba, ioc->ibase, ioc->imask);
+	}
+}
+
+static void
+sba_ioc_init_pluto(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
+{
 	u32 iova_space_mask;
 	u32 iova_space_size;
 	int iov_order, tcnfg;
-	struct parisc_device *lba;
 #if SBA_AGP_SUPPORT
 	int agp_found = 0;
 #endif
@@ -1461,14 +1472,7 @@ sba_ioc_init_pluto(struct parisc_device 
 #endif
 	sba_dump_tlb(ioc->ioc_hpa);
 
-	/*
-	** setup Mercury IBASE/IMASK registers as well.
-	*/
-	for (lba = sba->child; lba; lba = lba->sibling) {
-		int rope_num = (lba->hpa >> 13) & 0xf;
-		if (rope_num >> 3 == ioc_num)
-			lba_set_iregs(lba, ioc->ibase, ioc->imask);
-	}
+	setup_ibase_imask(sba, ioc, ioc_num);
 
 	WRITE_REG(ioc->imask, ioc->ioc_hpa + IOC_IMASK);
 
@@ -1534,13 +1538,9 @@ sba_ioc_init_pluto(struct parisc_device 
 static void
 sba_ioc_init(struct parisc_device *sba, struct ioc *ioc, int ioc_num)
 {
-	/* lba_set_iregs() is in arch/parisc/kernel/lba_pci.c */
-	extern void lba_set_iregs(struct parisc_device *, u32, u32);
-
 	u32 iova_space_size, iova_space_mask;
 	int pdir_size, iov_order;
 	unsigned long physmem;
-	struct parisc_device *lba;
 
 	/*
 	** Determine IOVA Space size from memory size.
@@ -1630,14 +1630,7 @@ sba_ioc_init(struct parisc_device *sba, 
 	** can't reprogram them the way drivers want.
 	*/
 
-	/*
-	** setup Elroy IBASE/IMASK registers as well.
-	*/
-	for (lba = sba->child; lba; lba = lba->sibling) {
-		int rope_num = (lba->hpa >> 13) & 0xf;
-		if (rope_num >> 3 == ioc_num)
-			lba_set_iregs(lba, ioc->ibase, ioc->imask);
-	}
+	setup_ibase_imask(sba, ioc, ioc_num);
 
 	/*
 	** Program the IOC's ibase and enable IOVA translation
@@ -1861,7 +1854,7 @@ sba_common_init(struct sba_device *sba_d
 			__FUNCTION__, i, res_size, sba_dev->ioc[i].res_map);
 	}
 
-	sba_dev->sba_lock = SPIN_LOCK_UNLOCKED;
+	spin_lock_init(&sba_dev->sba_lock);
 	ioc_needs_fdc = boot_cpu_data.pdc.capabilities & PDC_MODEL_IOPDIR_FDC;
 
 #ifdef DEBUG_SBA_INIT
@@ -2066,7 +2059,7 @@ sba_driver_callback(struct parisc_device
 		return(1);
 	}
 
-	dev->sysdata = (void *) sba_dev;
+	dev->dev.driver_data = sba_dev;
 	memset(sba_dev, 0, sizeof(struct sba_device));
 
 	for(i=0; i<MAX_IOC; i++)
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/parisc/wax.c parisc-2.6-bk/drivers/parisc/wax.c
--- linux-2.6.10-rc1-bk13/drivers/parisc/wax.c	Fri Oct 22 15:39:49 2004
+++ parisc-2.6-bk/drivers/parisc/wax.c	Wed Nov  3 06:19:06 2004
@@ -70,6 +70,7 @@ int __init
 wax_init_chip(struct parisc_device *dev)
 {
 	struct busdevice *wax;
+	struct parisc_device *parent;
 	struct gsc_irq gsc_irq;
 	int irq, ret;
 
@@ -118,8 +119,9 @@ wax_init_chip(struct parisc_device *dev)
 	fixup_child_irqs(dev, wax->busdev_region->data.irqbase,
 			wax_choose_irq);
 	/* On 715-class machines, Wax EISA is a sibling of Wax, not a child. */
-	if (dev->parent->id.hw_type != HPHW_IOA) {
-		fixup_child_irqs(dev->parent, wax->busdev_region->data.irqbase,
+	parent = parisc_parent(dev);
+	if (parent->id.hw_type != HPHW_IOA) {
+		fixup_child_irqs(parent, wax->busdev_region->data.irqbase,
 				wax_choose_irq);
 	}
 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/pci/probe.c parisc-2.6-bk/drivers/pci/probe.c
--- linux-2.6.10-rc1-bk13/drivers/pci/probe.c	Fri Oct 22 15:39:49 2004
+++ parisc-2.6-bk/drivers/pci/probe.c	Wed Nov  3 06:19:06 2004
@@ -478,6 +478,9 @@ static int pci_setup_device(struct pci_d
 	/* "Unknown power state" */
 	dev->current_state = 4;
 
+	/* Early fixups, before probing the BARs */
+	pci_fixup_device(pci_fixup_early, dev);
+
 	switch (dev->hdr_type) {		    /* header type */
 	case PCI_HEADER_TYPE_NORMAL:		    /* standard header */
 		if (class == PCI_CLASS_BRIDGE_PCI)
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/pci/quirks.c parisc-2.6-bk/drivers/pci/quirks.c
--- linux-2.6.10-rc1-bk13/drivers/pci/quirks.c	Wed Nov  3 05:57:46 2004
+++ parisc-2.6-bk/drivers/pci/quirks.c	Wed Nov  3 06:19:07 2004
@@ -545,7 +545,7 @@ static void __devinit quirk_cardbus_lega
 		return;
 	pci_write_config_dword(dev, PCI_CB_LEGACY_MODE_BASE, 0);
 }
-DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID,		PCI_ANY_ID,			quirk_cardbus_legacy );
+DECLARE_PCI_FIXUP_FINAL(PCI_ANY_ID, PCI_ANY_ID, quirk_cardbus_legacy);
 
 /*
  * Following the PCI ordering rules is optional on the AMD762. I'm not
@@ -663,7 +663,7 @@ static void __devinit quirk_ide_bases(st
        printk(KERN_INFO "PCI: Ignoring BAR%d-%d of IDE controller %s\n",
               first_bar, last_bar, pci_name(dev));
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID,             PCI_ANY_ID,                     quirk_ide_bases );
+DECLARE_PCI_FIXUP_HEADER(PCI_ANY_ID, PCI_ANY_ID, quirk_ide_bases);
 
 /*
  *	Ensure C0 rev restreaming is off. This is normally done by
@@ -1232,6 +1232,8 @@ static void pci_do_fixups(struct pci_dev
 	}
 }
 
+extern struct pci_fixup __start_pci_fixups_early[];
+extern struct pci_fixup __end_pci_fixups_early[];
 extern struct pci_fixup __start_pci_fixups_header[];
 extern struct pci_fixup __end_pci_fixups_header[];
 extern struct pci_fixup __start_pci_fixups_final[];
@@ -1245,6 +1247,11 @@ void pci_fixup_device(enum pci_fixup_pas
 	struct pci_fixup *start, *end;
 
 	switch(pass) {
+	case pci_fixup_early:
+		start = __start_pci_fixups_early;
+		end = __end_pci_fixups_early;
+		break;
+
 	case pci_fixup_header:
 		start = __start_pci_fixups_header;
 		end = __end_pci_fixups_header;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/pcmcia/Kconfig parisc-2.6-bk/drivers/pcmcia/Kconfig
--- linux-2.6.10-rc1-bk13/drivers/pcmcia/Kconfig	Fri Oct 22 15:39:50 2004
+++ parisc-2.6-bk/drivers/pcmcia/Kconfig	Wed Nov  3 06:19:07 2004
@@ -169,7 +169,11 @@ config PCMCIA_PXA2XX
 
 config PCMCIA_PROBE
 	bool
-	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X
+	default y if ISA && !ARCH_SA1100 && !ARCH_CLPS711X && !PARISC
+
+config PCMCIA_PROBE_MEM
+	bool
+	default y if !PARISC
 
 config M32R_PCC
 	bool "M32R PCMCIA I/F"
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/pcmcia/rsrc_mgr.c parisc-2.6-bk/drivers/pcmcia/rsrc_mgr.c
--- linux-2.6.10-rc1-bk13/drivers/pcmcia/rsrc_mgr.c	Fri Oct 22 15:39:43 2004
+++ parisc-2.6-bk/drivers/pcmcia/rsrc_mgr.c	Wed Nov  3 06:19:07 2004
@@ -59,7 +59,11 @@
 
 #define INT_MODULE_PARM(n, v) static int n = v; module_param(n, int, 0444)
 
+#ifdef CONFIG_PCMCIA_PROBE_MEM
 INT_MODULE_PARM(probe_mem,	1);		/* memory probe? */
+#else
+INT_MODULE_PARM(probe_mem,	0);		/* memory probe? */
+#endif
 #ifdef CONFIG_PCMCIA_PROBE
 INT_MODULE_PARM(probe_io,	1);		/* IO port probe? */
 INT_MODULE_PARM(mem_limit,	0x10000);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym53c8xx.h parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym53c8xx.h
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym53c8xx.h	Fri Oct 22 15:40:29 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym53c8xx.h	Wed Nov  3 06:19:08 2004
@@ -68,7 +68,6 @@
  */
 #if 1
 #define	SYM_LINUX_PROC_INFO_SUPPORT
-#define SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
 #define SYM_LINUX_USER_COMMAND_SUPPORT
 #define SYM_LINUX_USER_INFO_SUPPORT
 #define SYM_LINUX_DEBUG_CONTROL_SUPPORT
@@ -129,9 +128,7 @@ struct sym_driver_setup {
 	u_char	scsi_bus_check;
 	u_char	host_id;
 
-	u_char	reverse_probe;
 	u_char	verbose;
-	u_short	debug;
 	u_char	settle_delay;
 	u_char	use_nvram;
 	u_long	excludes[8];
@@ -145,6 +142,7 @@ struct sym_driver_setup {
 #define SYM_SETUP_IRQ_MODE		sym_driver_setup.irq_mode
 #define SYM_SETUP_SCSI_BUS_CHECK	sym_driver_setup.scsi_bus_check
 #define SYM_SETUP_HOST_ID		sym_driver_setup.host_id
+#define boot_verbose			sym_driver_setup.verbose
 
 /* Always enable parity. */
 #define SYM_SETUP_PCI_PARITY		1
@@ -163,54 +161,13 @@ struct sym_driver_setup {
 	.irq_mode	= 0,					\
 	.scsi_bus_check	= 1,					\
 	.host_id	= 7,					\
-	.reverse_probe	= 0,					\
 	.verbose	= 0,					\
-	.debug		= 0,					\
 	.settle_delay	= 3,					\
 	.use_nvram	= 1,					\
 }
 
-/*
- *  Boot fail safe setup.
- *
- *  Override initial setup from boot command line:
- *    sym53c8xx=safe:y
- */
-#define SYM_LINUX_DRIVER_SAFE_SETUP {				\
-	.max_tag	= 0,					\
-	.burst_order	= 0,					\
-	.scsi_led	= 0,					\
-	.scsi_diff	= 1,					\
-	.irq_mode	= 0,					\
-	.scsi_bus_check	= 2,					\
-	.host_id	= 7,					\
-	.reverse_probe	= 0,					\
-	.verbose	= 2,					\
-	.debug		= 0,					\
-	.settle_delay	= 10,					\
-	.use_nvram	= 1,					\
-}
-
-/*
- *  This structure is initialized from linux config options.
- *  It can be overridden at boot-up by the boot command line.
- */
-#ifdef SYM_GLUE_C
-struct sym_driver_setup
-	sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
-#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
-u_int	sym_debug_flags = 0;
-#endif
-#else
 extern struct sym_driver_setup sym_driver_setup;
-#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
-extern u_int sym_debug_flags;
-#endif
-#endif /* SYM_GLUE_C */
-
-#ifdef SYM_LINUX_DEBUG_CONTROL_SUPPORT
+extern unsigned int sym_debug_flags;
 #define DEBUG_FLAGS	sym_debug_flags
-#endif
-#define boot_verbose	sym_driver_setup.verbose
 
 #endif /* SYM53C8XX_H */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_conf.h parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_conf.h
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_conf.h	Fri Oct 22 15:40:05 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_conf.h	Wed Nov  3 06:19:08 2004
@@ -79,14 +79,6 @@
 /* #define SYM_CONF_IARB_SUPPORT */
 
 /*
- *  Number of lists for the optimization of the IO timeout handling.
- *  Not used under FreeBSD and Linux.
- */
-#ifndef SYM_CONF_TIMEOUT_ORDER_MAX
-#define SYM_CONF_TIMEOUT_ORDER_MAX	(8)
-#endif
-
-/*
  *  Only relevant if IARB support configured.
  *  - Max number of successive settings of IARB hints.
  *  - Set IARB on arbitration lost.
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_defs.h parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_defs.h
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_defs.h	Fri Oct 22 15:38:55 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_defs.h	Wed Nov  3 06:19:08 2004
@@ -40,33 +40,28 @@
 #ifndef SYM_DEFS_H
 #define SYM_DEFS_H
 
-#define SYM_VERSION "2.1.18k"
+#define SYM_VERSION "2.1.18m"
 #define SYM_DRIVER_NAME	"sym-" SYM_VERSION
 
 /*
- *  Vendor.
- */
-#define PCI_VENDOR_NCR		0x1000
-
-/*
  *  PCI device identifier of SYMBIOS chips.
  */
-#define PCI_ID_SYM53C810	1
-#define PCI_ID_SYM53C810AP	5
-#define PCI_ID_SYM53C815	4
-#define PCI_ID_SYM53C820	2
-#define PCI_ID_SYM53C825	3
-#define PCI_ID_SYM53C860	6
-#define PCI_ID_SYM53C875	0xf
-#define PCI_ID_SYM53C875_2	0x8f
-#define PCI_ID_SYM53C885	0xd
-#define PCI_ID_SYM53C895	0xc
-#define PCI_ID_SYM53C896	0xb
-#define PCI_ID_SYM53C895A	0x12
-#define PCI_ID_SYM53C875A	0x13
-#define PCI_ID_LSI53C1010_33	0x20
-#define PCI_ID_LSI53C1010_66	0x21
-#define PCI_ID_LSI53C1510D	0xa
+#define PCI_ID_SYM53C810	PCI_DEVICE_ID_NCR_53C810
+#define PCI_ID_SYM53C810AP	PCI_DEVICE_ID_LSI_53C810AP
+#define PCI_ID_SYM53C815	PCI_DEVICE_ID_NCR_53C815
+#define PCI_ID_SYM53C820	PCI_DEVICE_ID_NCR_53C820
+#define PCI_ID_SYM53C825	PCI_DEVICE_ID_NCR_53C825
+#define PCI_ID_SYM53C860	PCI_DEVICE_ID_NCR_53C860
+#define PCI_ID_SYM53C875	PCI_DEVICE_ID_NCR_53C875
+#define PCI_ID_SYM53C875_2	PCI_DEVICE_ID_NCR_53C875J
+#define PCI_ID_SYM53C885	PCI_DEVICE_ID_NCR_53C885
+#define PCI_ID_SYM53C895	PCI_DEVICE_ID_NCR_53C895
+#define PCI_ID_SYM53C896	PCI_DEVICE_ID_NCR_53C896
+#define PCI_ID_SYM53C895A	PCI_DEVICE_ID_LSI_53C895A
+#define PCI_ID_SYM53C875A	PCI_DEVICE_ID_LSI_53C875A
+#define PCI_ID_LSI53C1010_33	PCI_DEVICE_ID_LSI_53C1010_33
+#define PCI_ID_LSI53C1010_66	PCI_DEVICE_ID_LSI_53C1010_66
+#define PCI_ID_LSI53C1510D	PCI_DEVICE_ID_LSI_53C1510
 
 /*
  *	SYM53C8XX device features descriptor.
@@ -763,33 +758,32 @@ struct sym_tblsel {
  *	Messages
  */
 
-#define	M_COMPLETE	(0x00)
-#define	M_EXTENDED	(0x01)
-#define	M_SAVE_DP	(0x02)
-#define	M_RESTORE_DP	(0x03)
-#define	M_DISCONNECT	(0x04)
-#define	M_ID_ERROR	(0x05)
-#define	M_ABORT		(0x06)
-#define	M_REJECT	(0x07)
-#define	M_NOOP		(0x08)
-#define	M_PARITY	(0x09)
-#define	M_LCOMPLETE	(0x0a)
-#define	M_FCOMPLETE	(0x0b)
-#define	M_RESET		(0x0c)
+#define	M_COMPLETE	COMMAND_COMPLETE
+#define	M_EXTENDED	EXTENDED_MESSAGE
+#define	M_SAVE_DP	SAVE_POINTERS
+#define	M_RESTORE_DP	RESTORE_POINTERS
+#define	M_DISCONNECT	DISCONNECT
+#define	M_ID_ERROR	INITIATOR_ERROR
+#define	M_ABORT		ABORT
+#define	M_REJECT	MESSAGE_REJECT
+#define	M_NOOP		NOP
+#define	M_PARITY	MSG_PARITY_ERROR
+#define	M_LCOMPLETE	LINKED_CMD_COMPLETE
+#define	M_FCOMPLETE	LINKED_FLG_CMD_COMPLETE
+#define	M_RESET		BUS_DEVICE_RESET
 #define	M_ABORT_TAG	(0x0d)
 #define	M_CLEAR_QUEUE	(0x0e)
-#define	M_INIT_REC	(0x0f)
-#define	M_REL_REC	(0x10)
+#define	M_INIT_REC	INITIATE_RECOVERY
+#define	M_REL_REC	RELEASE_RECOVERY
 #define	M_TERMINATE	(0x11)
-#define	M_SIMPLE_TAG	(0x20)
-#define	M_HEAD_TAG	(0x21)
-#define	M_ORDERED_TAG	(0x22)
+#define	M_SIMPLE_TAG	SIMPLE_QUEUE_TAG
+#define	M_HEAD_TAG	HEAD_OF_QUEUE_TAG
+#define	M_ORDERED_TAG	ORDERED_QUEUE_TAG
 #define	M_IGN_RESIDUE	(0x23)
-#define	M_IDENTIFY   	(0x80)
 
-#define	M_X_MODIFY_DP	(0x00)
-#define	M_X_SYNC_REQ	(0x01)
-#define	M_X_WIDE_REQ	(0x03)
+#define	M_X_MODIFY_DP	EXTENDED_MODIFY_DATA_POINTER
+#define	M_X_SYNC_REQ	EXTENDED_SDTR
+#define	M_X_WIDE_REQ	EXTENDED_WDTR
 #define	M_X_PPR_REQ	(0x04)
 
 /*
@@ -804,15 +798,15 @@ struct sym_tblsel {
  *	Status
  */
 
-#define	S_GOOD		(0x00)
-#define	S_CHECK_COND	(0x02)
-#define	S_COND_MET	(0x04)
-#define	S_BUSY		(0x08)
-#define	S_INT		(0x10)
-#define	S_INT_COND_MET	(0x14)
-#define	S_CONFLICT	(0x18)
-#define	S_TERMINATED	(0x20)
-#define	S_QUEUE_FULL	(0x28)
+#define	S_GOOD		SAM_STAT_GOOD
+#define	S_CHECK_COND	SAM_STAT_CHECK_CONDITION
+#define	S_COND_MET	SAM_STAT_CONDITION_MET
+#define	S_BUSY		SAM_STAT_BUSY
+#define	S_INT		SAM_STAT_INTERMEDIATE
+#define	S_INT_COND_MET	SAM_STAT_INTERMEDIATE_CONDITION_MET
+#define	S_CONFLICT	SAM_STAT_RESERVATION_CONFLICT
+#define	S_TERMINATED	SAM_STAT_COMMAND_TERMINATED
+#define	S_QUEUE_FULL	SAM_STAT_TASK_SET_FULL
 #define	S_ILLEGAL	(0xff)
 
 #endif /* defined SYM_DEFS_H */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_glue.c parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_glue.c
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_glue.c	Fri Oct 22 15:40:35 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_glue.c	Wed Nov  3 06:19:08 2004
@@ -37,12 +37,11 @@
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
-#define SYM_GLUE_C
-
 #include <linux/ctype.h>
 #include <linux/init.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
+#include <linux/moduleparam.h>
 #include <linux/spinlock.h>
 #include <scsi/scsi.h>
 #include <scsi/scsi_tcq.h>
@@ -56,6 +55,86 @@
 #define NAME53C		"sym53c"
 #define NAME53C8XX	"sym53c8xx"
 
+/* SPARC just has to be different ... */
+#ifdef __sparc__
+#define IRQ_FMT "%s"
+#define IRQ_PRM(x) __irq_itoa(x)
+#else
+#define IRQ_FMT "%d"
+#define IRQ_PRM(x) (x)
+#endif
+
+struct sym_driver_setup sym_driver_setup = SYM_LINUX_DRIVER_SETUP;
+unsigned int sym_debug_flags = 0;
+
+static char *excl_string;
+static char *safe_string;
+module_param_named(cmd_per_lun, sym_driver_setup.max_tag, ushort, 0);
+module_param_string(tag_ctrl, sym_driver_setup.tag_ctrl, 100, 0);
+module_param_named(burst, sym_driver_setup.burst_order, byte, 0);
+module_param_named(led, sym_driver_setup.scsi_led, byte, 0);
+module_param_named(diff, sym_driver_setup.scsi_diff, byte, 0);
+module_param_named(irqm, sym_driver_setup.irq_mode, byte, 0);
+module_param_named(buschk, sym_driver_setup.scsi_bus_check, byte, 0);
+module_param_named(hostid, sym_driver_setup.host_id, byte, 0);
+module_param_named(verb, sym_driver_setup.verbose, byte, 0);
+module_param_named(debug, sym_debug_flags, uint, 0);
+module_param_named(settle, sym_driver_setup.settle_delay, byte, 0);
+module_param_named(nvram, sym_driver_setup.use_nvram, byte, 0);
+module_param_named(excl, excl_string, charp, 0);
+module_param_named(safe, safe_string, charp, 0);
+
+MODULE_PARM_DESC(cmd_per_lun, "The maximum number of tags to use by default");
+MODULE_PARM_DESC(tag_ctrl, "More detailed control over tags per LUN");
+MODULE_PARM_DESC(burst, "Maximum burst.  0 to disable, 255 to read from registers");
+MODULE_PARM_DESC(led, "Set to 1 to enable LED support");
+MODULE_PARM_DESC(diff, "0 for no differential mode, 1 for BIOS, 2 for always, 3 for not GPIO3");
+MODULE_PARM_DESC(irqm, "0 for open drain, 1 to leave alone, 2 for totem pole");
+MODULE_PARM_DESC(buschk, "0 to not check, 1 for detach on error, 2 for warn on error");
+MODULE_PARM_DESC(hostid, "The SCSI ID to use for the host adapters");
+MODULE_PARM_DESC(verb, "0 for minimal verbosity, 1 for normal, 2 for excessive");
+MODULE_PARM_DESC(debug, "Set bits to enable debugging");
+MODULE_PARM_DESC(settle, "Settle delay in seconds.  Default 3");
+MODULE_PARM_DESC(nvram, "Option currently not used");
+MODULE_PARM_DESC(excl, "List ioport addresses here to prevent controllers from being attached");
+MODULE_PARM_DESC(safe, "Set other settings to a \"safe mode\"");
+
+MODULE_LICENSE("GPL");
+MODULE_VERSION(SYM_VERSION);
+MODULE_AUTHOR("Matthew Wilcox <matthew@wil.cx>");
+MODULE_DESCRIPTION("NCR, Symbios and LSI 8xx and 1010 PCI SCSI adapters");
+
+static void sym2_setup_params(void)
+{
+	char *p = excl_string;
+	int xi = 0;
+
+	while (p && (xi < 8)) {
+		char *next_p;
+		int val = (int) simple_strtoul(p, &next_p, 0);
+		sym_driver_setup.excludes[xi++] = val;
+		p = next_p;
+	}
+
+	if (safe_string) {
+		if (*safe_string == 'y') {
+			sym_driver_setup.max_tag = 0;
+			sym_driver_setup.burst_order = 0;
+			sym_driver_setup.scsi_led = 0;
+			sym_driver_setup.scsi_diff = 1;
+			sym_driver_setup.irq_mode = 0;
+			sym_driver_setup.scsi_bus_check = 2;
+			sym_driver_setup.host_id = 7;
+			sym_driver_setup.verbose = 2;
+			sym_driver_setup.settle_delay = 10;
+			sym_driver_setup.use_nvram = 1;
+		} else if (*safe_string != 'n') {
+			printk(KERN_WARNING NAME53C8XX "Ignoring parameter %s"
+					" passed to safe option", safe_string);
+		}
+	}
+}
+
 static int __devinit
 pci_get_base_address(struct pci_dev *pdev, int index, u_long *base)
 {
@@ -135,7 +214,7 @@ m_addr_t __vtobus(m_pool_ident_t dev_dma
  *  It is allocated on the eh thread stack.
  */
 struct sym_eh_wait {
-	struct semaphore sem;
+	struct completion done;
 	struct timer_list timer;
 	void (*old_done)(struct scsi_cmnd *);
 	int to_do;
@@ -146,7 +225,6 @@ struct sym_eh_wait {
  *  Driver private area in the SCSI command structure.
  */
 struct sym_ucmd {		/* Override the SCSI pointer structure */
-	SYM_QUEHEAD link_cmdq;	/* Must stay at offset ZERO */
 	dma_addr_t data_mapping;
 	u_char	data_mapped;
 	struct sym_eh_wait *eh_wait;
@@ -212,7 +290,6 @@ static int __map_scsi_sg_data(struct pci
  */
 void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb)
 {
-	sym_remque(&SYM_UCMD_PTR(ccb)->link_cmdq);
 	unmap_scsi_data(np, ccb);
 	ccb->scsi_done(ccb);
 }
@@ -311,7 +388,7 @@ void sym_set_cam_result_error(struct sym
 			/*
 			 *  Bounce back the sense data to user.
 			 */
-			bzero(&csio->sense_buffer, sizeof(csio->sense_buffer));
+			memset(&csio->sense_buffer, 0, sizeof(csio->sense_buffer));
 			memcpy(csio->sense_buffer, cp->sns_bbuf,
 			      min(sizeof(csio->sense_buffer),
 				  (size_t)SYM_SNS_BBUF_LEN));
@@ -648,31 +725,6 @@ void sym_log_bus_error(struct sym_hcb *n
 	}
 }
 
-
-/*
- *  Requeue awaiting commands.
- */
-static void sym_requeue_awaiting_cmds(struct sym_hcb *np)
-{
-	struct sym_ucmd *ucp;
-	SYM_QUEHEAD tmp_cmdq;
-	int sts;
-
-	sym_que_move(&np->s.wait_cmdq, &tmp_cmdq);
-
-	while ((ucp = (struct sym_ucmd *) sym_remque_head(&tmp_cmdq)) != 0) {
-		struct scsi_cmnd *cmd;
-
-		sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
-		cmd = SYM_SCMD_PTR(ucp);
-		sts = sym_queue_command(np, cmd);
-		if (sts) {
-			sym_remque(&ucp->link_cmdq);
-			sym_insque_head(&ucp->link_cmdq, &np->s.wait_cmdq);
-		}
-	}
-}
-
 /*
  * queuecommand method.  Entered with the host adapter lock held and
  * interrupts disabled.
@@ -700,18 +752,12 @@ static int sym53c8xx_queue_command(struc
 		}
 	}
 
-	if (np->s.settle_time_valid || !sym_que_empty(&np->s.wait_cmdq)) {
-		sym_insque_tail(&ucp->link_cmdq, &np->s.wait_cmdq);
-		goto out;
-	}
+	if (np->s.settle_time_valid)
+		return SCSI_MLQUEUE_HOST_BUSY;
 
-	sym_insque_tail(&ucp->link_cmdq, &np->s.busy_cmdq);
 	sts = sym_queue_command(np, cmd);
-	if (sts) {
-		sym_remque(&ucp->link_cmdq);
-		sym_insque_tail(&ucp->link_cmdq, &np->s.wait_cmdq);
-	}
-out:
+	if (sts)
+		return SCSI_MLQUEUE_HOST_BUSY;
 	return 0;
 }
 
@@ -726,15 +772,7 @@ static irqreturn_t sym53c8xx_intr(int ir
 	if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("[");
 
 	spin_lock_irqsave(np->s.host->host_lock, flags);
-
 	sym_interrupt(np);
-
-	/*
-	 * push queue walk-through to tasklet
-	 */
-	if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid)
-		sym_requeue_awaiting_cmds(np);
-
 	spin_unlock_irqrestore(np->s.host->host_lock, flags);
 
 	if (DEBUG_FLAGS & DEBUG_TINY) printf_debug ("]\n");
@@ -751,12 +789,7 @@ static void sym53c8xx_timer(unsigned lon
 	unsigned long flags;
 
 	spin_lock_irqsave(np->s.host->host_lock, flags);
-
 	sym_timer(np);
-
-	if (!sym_que_empty(&np->s.wait_cmdq) && !np->s.settle_time_valid)
-		sym_requeue_awaiting_cmds(np);
-
 	spin_unlock_irqrestore(np->s.host->host_lock, flags);
 }
 
@@ -798,7 +831,7 @@ static void __sym_eh_done(struct scsi_cm
 
 	/* Wake up the eh thread if it wants to sleep */
 	if (ep->to_do == SYM_EH_DO_WAIT)
-		up(&ep->sem);
+		complete(&ep->done);
 }
 
 /*
@@ -834,14 +867,6 @@ static int sym_eh_handler(int op, char *
 		goto prepare;
 #endif
 
-	/* This one is not queued to the core driver -> to complete here */ 
-	FOR_EACH_QUEUED_ELEMENT(&np->s.wait_cmdq, qp) {
-		if (SYM_SCMD_PTR(qp) == cmd) {
-			to_do = SYM_EH_DO_COMPLETE;
-			goto prepare;
-		}
-	}
-
 	/* This one is queued in some place -> to wait for completion */
 	FOR_EACH_QUEUED_ELEMENT(&np->busy_ccbq, qp) {
 		struct sym_ccb *cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
@@ -858,7 +883,7 @@ prepare:
 	case SYM_EH_DO_IGNORE:
 		break;
 	case SYM_EH_DO_WAIT:
-		init_MUTEX_LOCKED(&ep->sem);
+		init_completion(&ep->done);
 		/* fall through */
 	case SYM_EH_DO_COMPLETE:
 		ep->old_done = cmd->scsi_done;
@@ -909,7 +934,7 @@ prepare:
 		ep->timed_out = 1;	/* Be pessimistic for once :) */
 		add_timer(&ep->timer);
 		spin_unlock_irq(np->s.host->host_lock);
-		down(&ep->sem);
+		wait_for_completion(&ep->done);
 		spin_lock_irq(np->s.host->host_lock);
 		if (ep->timed_out)
 			sts = -2;
@@ -973,7 +998,6 @@ static void sym_tune_dev_queuing(struct 
 	}
 }
 
-#ifdef	SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
 /*
  *  Linux select queue depths function
  */
@@ -1026,9 +1050,6 @@ static int device_queue_depth(struct sym
 	}
 	return DEF_DEPTH;
 }
-#else
-#define device_queue_depth(np, t, l)	(sym_driver_setup.max_tag)
-#endif	/* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
 
 /*
  * Linux entry point for device queue sizing.
@@ -1164,7 +1185,7 @@ static void sym_exec_user_command (struc
 				if (uc->data <= 9 && np->minsync_dt) {
 					if (uc->data < np->minsync_dt)
 						uc->data = np->minsync_dt;
-					tp->tinfo.goal.options = PPR_OPT_DT;
+					tp->tinfo.goal.options = PPR_OPT_MASK;
 					tp->tinfo.goal.width   = 1;
 					tp->tinfo.goal.period = uc->data;
 					tp->tinfo.goal.offset = np->maxoffs_dt;
@@ -1265,7 +1286,7 @@ static int sym_user_command(struct sym_h
 	int		arg_len;
 	u_long 		target;
 
-	bzero(uc, sizeof(*uc));
+	memset(uc, 0, sizeof(*uc));
 
 	if (len > 0 && ptr[len-1] == '\n')
 		--len;
@@ -1455,18 +1476,8 @@ static int sym_host_info(struct sym_hcb 
 	copy_info(&info, "Chip " NAME53C "%s, device id 0x%x, "
 			 "revision id 0x%x\n",
 			 np->s.chip_name, np->device_id, np->revision_id);
-	copy_info(&info, "At PCI address %s, "
-#ifdef __sparc__
-		"IRQ %s\n",
-#else
-		"IRQ %d\n",
-#endif
-		pci_name(np->s.device),
-#ifdef __sparc__
-		__irq_itoa(np->s.irq));
-#else
-		(int) np->s.irq);
-#endif
+	copy_info(&info, "At PCI address %s, IRQ " IRQ_FMT "\n",
+		pci_name(np->s.device), IRQ_PRM(np->s.irq));
 	copy_info(&info, "Min. period factor %d, %s SCSI BUS%s\n",
 			 (int) (np->minsync_dt ? np->minsync_dt : np->minsync),
 			 np->maxwide ? "Wide" : "Narrow",
@@ -1594,19 +1605,9 @@ static struct Scsi_Host * __devinit sym_
 	struct sym_fw *fw;
 
 	printk(KERN_INFO
-		"sym%d: <%s> rev 0x%x at pci %s "
-#ifdef __sparc__
-		"irq %s\n",
-#else
-		"irq %d\n",
-#endif
+		"sym%d: <%s> rev 0x%x at pci %s irq " IRQ_FMT "\n",
 		unit, dev->chip.name, dev->chip.revision_id,
-		pci_name(dev->pdev),
-#ifdef __sparc__
-		__irq_itoa(dev->s.irq));
-#else
-		dev->s.irq);
-#endif
+		pci_name(dev->pdev), IRQ_PRM(dev->s.irq));
 
 	/*
 	 *  Get the firmware for this chip.
@@ -1732,12 +1733,6 @@ static struct Scsi_Host * __devinit sym_
 		goto reset_failed;
 
 	/*
-	 *  Initialize some queue headers.
-	 */
-	sym_que_init(&np->s.wait_cmdq);
-	sym_que_init(&np->s.busy_cmdq);
-
-	/*
 	 *  Start the SCRIPTS.
 	 */
 	sym_start_up (np, 1);
@@ -1828,145 +1823,6 @@ static inline void sym_get_nvram(struct 
 }
 #endif	/* SYM_CONF_NVRAM_SUPPORT */
 
-/*
- *  Driver setup from the boot command line
- */
-#ifdef	SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
-
-static struct sym_driver_setup
-	sym_driver_safe_setup __initdata = SYM_LINUX_DRIVER_SAFE_SETUP;
-#ifdef	MODULE
-char *sym53c8xx;	/* command line passed by insmod */
-MODULE_PARM(sym53c8xx, "s");
-#endif
-
-#define OPT_MAX_TAG		1
-#define OPT_BURST_ORDER		2
-#define OPT_SCSI_LED		3
-#define OPT_SCSI_DIFF		4
-#define OPT_IRQ_MODE		5
-#define OPT_SCSI_BUS_CHECK	6
-#define	OPT_HOST_ID		7
-#define OPT_REVERSE_PROBE	8
-#define OPT_VERBOSE		9
-#define OPT_DEBUG		10
-#define OPT_SETTLE_DELAY	11
-#define OPT_USE_NVRAM		12
-#define OPT_EXCLUDE		13
-#define OPT_SAFE_SETUP		14
-
-static char setup_token[] __initdata =
-	"tags:"		"burst:"
-	"led:"		"diff:"
-	"irqm:"		"buschk:"
-	"hostid:"	"revprob:"
-	"verb:"		"debug:"
-	"settle:"	"nvram:"
-	"excl:"		"safe:"
-	;
-
-#ifdef MODULE
-#define	ARG_SEP	' '
-#else
-#define	ARG_SEP	','
-#endif
-
-static int __init get_setup_token(char *p)
-{
-	char *cur = setup_token;
-	char *pc;
-	int i = 0;
-
-	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-		++pc;
-		++i;
-		if (!strncmp(p, cur, pc - cur))
-			return i;
-		cur = pc;
-	}
-	return 0;
-}
-#endif	/* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
-
-int __init sym53c8xx_setup(char *str)
-{
-#ifdef	SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT
-	char *cur = str;
-	char *pc, *pv;
-	unsigned long val;
-	unsigned int i,  c;
-	int xi = 0;
-
-	while (cur != NULL && (pc = strchr(cur, ':')) != NULL) {
-		char *pe;
-
-		val = 0;
-		pv = pc;
-		c = *++pv;
-
-		if	(c == 'n')
-			val = 0;
-		else if	(c == 'y')
-			val = 1;
-		else
-			val = (int) simple_strtoul(pv, &pe, 0);
-
-		switch (get_setup_token(cur)) {
-		case OPT_MAX_TAG:
-			sym_driver_setup.max_tag = val;
-			if (!(pe && *pe == '/'))
-				break;
-			i = 0;
-			while (*pe && *pe != ARG_SEP && 
-				i < sizeof(sym_driver_setup.tag_ctrl)-1) {
-				sym_driver_setup.tag_ctrl[i++] = *pe++;
-			}
-			sym_driver_setup.tag_ctrl[i] = '\0';
-			break;
-		case OPT_SAFE_SETUP:
-			memcpy(&sym_driver_setup, &sym_driver_safe_setup,
-				sizeof(sym_driver_setup));
-			break;
-		case OPT_EXCLUDE:
-			if (xi < 8)
-				sym_driver_setup.excludes[xi++] = val;
-			break;
-
-#define __SIMPLE_OPTION(NAME, name) \
-		case OPT_ ## NAME :		\
-			sym_driver_setup.name = val;\
-			break;
-
-		__SIMPLE_OPTION(BURST_ORDER, burst_order)
-		__SIMPLE_OPTION(SCSI_LED, scsi_led)
-		__SIMPLE_OPTION(SCSI_DIFF, scsi_diff)
-		__SIMPLE_OPTION(IRQ_MODE, irq_mode)
-		__SIMPLE_OPTION(SCSI_BUS_CHECK, scsi_bus_check)
-		__SIMPLE_OPTION(HOST_ID, host_id)
-		__SIMPLE_OPTION(REVERSE_PROBE, reverse_probe)
-		__SIMPLE_OPTION(VERBOSE, verbose)
-		__SIMPLE_OPTION(DEBUG, debug)
-		__SIMPLE_OPTION(SETTLE_DELAY, settle_delay)
-		__SIMPLE_OPTION(USE_NVRAM, use_nvram)
-
-#undef __SIMPLE_OPTION
-
-		default:
-			printk("sym53c8xx_setup: unexpected boot option '%.*s' ignored\n", (int)(pc-cur+1), cur);
-			break;
-		}
-
-		if ((cur = strchr(cur, ARG_SEP)) != NULL)
-			++cur;
-	}
-#endif	/* SYM_LINUX_BOOT_COMMAND_LINE_SUPPORT */
-	return 1;
-}
-
-#ifndef MODULE
-__setup("sym53c8xx=", sym53c8xx_setup);
-#endif
-
 static int __devinit sym_check_supported(struct sym_device *device)
 {
 	struct sym_pci_chip *chip;
@@ -2029,7 +1885,7 @@ static int __devinit sym_check_raid(stru
 {
 	unsigned long base_2_c = device->s.base_2_c;
 	unsigned int ram_size, ram_val;
-	void *ram_ptr;
+	void __iomem *ram_ptr;
 
 	if (!base_2_c)
 		return 0;
@@ -2111,6 +1967,7 @@ sym_init_device(struct pci_dev *pdev, st
 	unsigned long base, base_2; 
 	int i;
 
+	device->host_id = SYM_SETUP_HOST_ID;
 	device->pdev = pdev;
 	device->s.irq = pdev->irq;
 
@@ -2145,9 +2002,9 @@ sym_init_device(struct pci_dev *pdev, st
 void sym_config_pqs(struct pci_dev *pdev, struct sym_device *sym_dev)
 {
 	int slot;
+	u8 tmp;
 
 	for (slot = 0; slot < 256; slot++) {
-		u8 tmp;
 		struct pci_dev *memc = pci_get_slot(pdev->bus, slot);
 
 		if (!memc || memc->vendor != 0x101a || memc->device == 0x0009) {
@@ -2155,28 +2012,26 @@ void sym_config_pqs(struct pci_dev *pdev
 			continue;
 		}
 
-		/*
-		 * We set these bits in the memory controller once per 875.
-		 * This isn't a problem in practice.
-		 */
-
 		/* bit 1: allow individual 875 configuration */
 		pci_read_config_byte(memc, 0x44, &tmp);
-		tmp |= 0x2;
-		pci_write_config_byte(memc, 0x44, tmp);
+		if ((tmp & 0x2) == 0) {
+			tmp |= 0x2;
+			pci_write_config_byte(memc, 0x44, tmp);
+		}
 
 		/* bit 2: drive individual 875 interrupts to the bus */
 		pci_read_config_byte(memc, 0x45, &tmp);
-		tmp |= 0x4;
-		pci_write_config_byte(memc, 0x45, tmp);
-
-		pci_read_config_byte(pdev, 0x84, &tmp);
-		sym_dev->host_id = tmp;
+		if ((tmp & 0x4) == 0) {
+			tmp |= 0x4;
+			pci_write_config_byte(memc, 0x45, tmp);
+		}
 
 		pci_dev_put(memc);
-
 		break;
 	}
+
+	pci_read_config_byte(pdev, 0x84, &tmp);
+	sym_dev->host_id = tmp;
 }
 
 /*
@@ -2205,9 +2060,6 @@ static int sym_detach(struct sym_hcb *np
 	return 1;
 }
 
-MODULE_LICENSE("GPL");
-MODULE_VERSION(SYM_VERSION);
-
 /*
  * Driver host template.
  */
@@ -2249,8 +2101,6 @@ static int __devinit sym2_probe(struct p
 	if (pci_request_regions(pdev, NAME53C8XX))
 		goto disable;
 
-	sym_dev.host_id = SYM_SETUP_HOST_ID;
-
 	sym_init_device(pdev, &sym_dev);
 	if (sym_check_supported(&sym_dev))
 		goto free;
@@ -2381,9 +2231,10 @@ static void sym2_set_width(struct scsi_t
 	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[starget->id];
 
-	/* It is illegal to have DT set on narrow transfers */
+	/* It is illegal to have DT set on narrow transfers.  If DT is
+	 * clear, we must also clear IU and QAS.  */
 	if (width == 0)
-		tp->tinfo.goal.options &= ~PPR_OPT_DT;
+		tp->tinfo.goal.options &= ~PPR_OPT_MASK;
 
 	tp->tinfo.goal.width = width;
 }
@@ -2403,12 +2254,55 @@ static void sym2_set_dt(struct scsi_targ
 	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
 	struct sym_tcb *tp = &np->target[starget->id];
 
+	/* We must clear QAS and IU if DT is clear */
 	if (dt)
 		tp->tinfo.goal.options |= PPR_OPT_DT;
 	else
-		tp->tinfo.goal.options &= ~PPR_OPT_DT;
+		tp->tinfo.goal.options &= ~PPR_OPT_MASK;
+}
+
+static void sym2_get_iu(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	spi_iu(starget) = (tp->tinfo.curr.options & PPR_OPT_IU) ? 1 : 0;
+}
+
+static void sym2_set_iu(struct scsi_target *starget, int iu)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	if (iu)
+		tp->tinfo.goal.options |= PPR_OPT_IU | PPR_OPT_DT;
+	else
+		tp->tinfo.goal.options &= ~PPR_OPT_IU;
 }
-	
+
+static void sym2_get_qas(struct scsi_target *starget)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	spi_qas(starget) = (tp->tinfo.curr.options & PPR_OPT_QAS) ? 1 : 0;
+}
+
+static void sym2_set_qas(struct scsi_target *starget, int qas)
+{
+	struct Scsi_Host *shost = dev_to_shost(starget->dev.parent);
+	struct sym_hcb *np = ((struct host_data *)shost->hostdata)->ncb;
+	struct sym_tcb *tp = &np->target[starget->id];
+
+	if (qas)
+		tp->tinfo.goal.options |= PPR_OPT_QAS | PPR_OPT_DT;
+	else
+		tp->tinfo.goal.options &= ~PPR_OPT_QAS;
+}
+
 
 static struct spi_function_template sym2_transport_functions = {
 	.set_offset	= sym2_set_offset,
@@ -2423,6 +2317,12 @@ static struct spi_function_template sym2
 	.get_dt		= sym2_get_dt,
 	.set_dt		= sym2_set_dt,
 	.show_dt	= 1,
+	.get_iu		= sym2_get_iu,
+	.set_iu		= sym2_set_iu,
+	.show_iu	= 1,
+	.get_qas	= sym2_get_qas,
+	.set_qas	= sym2_set_qas,
+	.show_qas	= 1,
 	.get_signalling	= sym2_get_signalling,
 };
 
@@ -2475,12 +2375,17 @@ static struct pci_driver sym2_driver = {
 
 static int __init sym2_init(void)
 {
+	int error;
+
+	sym2_setup_params();
 	sym2_transport_template = spi_attach_transport(&sym2_transport_functions);
 	if (!sym2_transport_template)
 		return -ENODEV;
 
-	pci_register_driver(&sym2_driver);
-	return 0;
+	error = pci_module_init(&sym2_driver);
+	if (error)
+		spi_release_transport(sym2_transport_template);
+	return error;
 }
 
 static void __exit sym2_exit(void)
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_glue.h parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_glue.h
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_glue.h	Fri Oct 22 15:40:29 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_glue.h	Wed Nov  3 06:19:08 2004
@@ -58,13 +58,6 @@
 #include <scsi/scsi_device.h>
 #include <scsi/scsi_host.h>
 
-#ifndef bzero
-#define bzero(d, n)	memset((d), 0, (n))
-#endif
-
-/*
- *  General driver includes.
- */
 #include "sym_conf.h"
 #include "sym_defs.h"
 #include "sym_misc.h"
@@ -123,14 +116,6 @@
 typedef struct sym_tcb *tcb_p;
 typedef struct sym_lcb *lcb_p;
 typedef struct sym_ccb *ccb_p;
-typedef struct sym_hcb *hcb_p;
-
-/*
- *  Define a reference to the O/S dependent IO request.
- */
-typedef struct scsi_cmnd *cam_ccb_p;	/* Generic */
-typedef struct scsi_cmnd *cam_scsiio_p;/* SCSI I/O */
-
 
 /*
  *  IO functions definition for big/little endian CPU support.
@@ -381,9 +366,6 @@ struct sym_shcb {
 	u_short		io_ws;		/* IO window size		*/
 	int		irq;		/* IRQ number			*/
 
-	SYM_QUEHEAD	wait_cmdq;	/* Awaiting SCSI commands	*/
-	SYM_QUEHEAD	busy_cmdq;	/* Enqueued SCSI commands	*/
-
 	struct timer_list timer;	/* Timer handler link header	*/
 	u_long		lasttime;
 	u_long		settle_time;	/* Resetting the SCSI BUS	*/
@@ -528,7 +510,7 @@ sym_get_cam_status(struct scsi_cmnd *ccb
 /*
  *  Async handler for negotiations.
  */
-void sym_xpt_async_nego_wide(hcb_p np, int target);
+void sym_xpt_async_nego_wide(struct sym_hcb *np, int target);
 #define sym_xpt_async_nego_sync(np, target)	\
 	sym_announce_transfer_rate(np, target)
 #define sym_xpt_async_nego_ppr(np, target)	\
@@ -537,14 +519,14 @@ void sym_xpt_async_nego_wide(hcb_p np, i
 /*
  *  Build CAM result for a successful IO and for a failed IO.
  */
-static __inline void sym_set_cam_result_ok(hcb_p np, ccb_p cp, int resid)
+static __inline void sym_set_cam_result_ok(struct sym_hcb *np, ccb_p cp, int resid)
 {
 	struct scsi_cmnd *cmd = cp->cam_ccb;
 
 	cmd->resid = resid;
 	cmd->result = (((DID_OK) << 16) + ((cp->ssss_status) & 0x7f));
 }
-void sym_set_cam_result_error(hcb_p np, ccb_p cp, int resid);
+void sym_set_cam_result_error(struct sym_hcb *np, ccb_p cp, int resid);
 
 /*
  *  Other O/S specific methods.
@@ -552,13 +534,13 @@ void sym_set_cam_result_error(hcb_p np, 
 #define sym_cam_target_id(ccb)	(ccb)->target
 #define sym_cam_target_lun(ccb)	(ccb)->lun
 #define	sym_freeze_cam_ccb(ccb)	do { ; } while (0)
-void sym_xpt_done(hcb_p np, cam_ccb_p ccb);
-void sym_xpt_done2(hcb_p np, cam_ccb_p ccb, int cam_status);
+void sym_xpt_done(struct sym_hcb *np, struct scsi_cmnd *ccb);
+void sym_xpt_done2(struct sym_hcb *np, struct scsi_cmnd *ccb, int cam_status);
 void sym_print_addr (ccb_p cp);
-void sym_xpt_async_bus_reset(hcb_p np);
-void sym_xpt_async_sent_bdr(hcb_p np, int target);
-int  sym_setup_data_and_start (hcb_p np, cam_scsiio_p csio, ccb_p cp);
-void sym_log_bus_error(hcb_p np);
-void sym_sniff_inquiry(hcb_p np, struct scsi_cmnd *cmd, int resid);
+void sym_xpt_async_bus_reset(struct sym_hcb *np);
+void sym_xpt_async_sent_bdr(struct sym_hcb *np, int target);
+int  sym_setup_data_and_start (struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+void sym_log_bus_error(struct sym_hcb *np);
+void sym_sniff_inquiry(struct sym_hcb *np, struct scsi_cmnd *cmd, int resid);
 
 #endif /* SYM_GLUE_H */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_hipd.c parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_hipd.c
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_hipd.c	Fri Oct 22 15:38:02 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_hipd.c	Wed Nov  3 06:19:09 2004
@@ -47,14 +47,14 @@
 /*
  *  Needed function prototypes.
  */
-static void sym_int_ma (hcb_p np);
-static void sym_int_sir (hcb_p np);
-static ccb_p sym_alloc_ccb(hcb_p np);
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa);
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln);
-static void sym_complete_error (hcb_p np, ccb_p cp);
-static void sym_complete_ok (hcb_p np, ccb_p cp);
-static int sym_compute_residual(hcb_p np, ccb_p cp);
+static void sym_int_ma (struct sym_hcb *np);
+static void sym_int_sir (struct sym_hcb *np);
+static ccb_p sym_alloc_ccb(struct sym_hcb *np);
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa);
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln);
+static void sym_complete_error (struct sym_hcb *np, ccb_p cp);
+static void sym_complete_ok (struct sym_hcb *np, ccb_p cp);
+static int sym_compute_residual(struct sym_hcb *np, ccb_p cp);
 
 /*
  *  Returns the name of this driver.
@@ -86,12 +86,12 @@ static void sym_printl_hex (char *label,
  *  Print something which allows to retrieve the controler type, 
  *  unit, target, lun concerned by a kernel message.
  */
-static void sym_print_target (hcb_p np, int target)
+static void sym_print_target (struct sym_hcb *np, int target)
 {
 	printf ("%s:%d:", sym_name(np), target);
 }
 
-static void sym_print_lun(hcb_p np, int target, int lun)
+static void sym_print_lun(struct sym_hcb *np, int target, int lun)
 {
 	printf ("%s:%d:%d:", sym_name(np), target, lun);
 }
@@ -126,7 +126,7 @@ static void sym_print_msg (ccb_p cp, cha
 	printf (".\n");
 }
 
-static void sym_print_nego_msg (hcb_p np, int target, char *label, u_char *msg)
+static void sym_print_nego_msg (struct sym_hcb *np, int target, char *label, u_char *msg)
 {
 	PRINT_TARGET(np, target);
 	if (label)
@@ -184,7 +184,7 @@ static char *sym_scsi_bus_mode(int mode)
  *  On the other hand, LVD devices need some delay 
  *  to settle and report actual BUS mode in STEST4.
  */
-static void sym_chip_reset (hcb_p np)
+static void sym_chip_reset (struct sym_hcb *np)
 {
 	OUTB (nc_istat, SRST);
 	UDELAY (10);
@@ -201,7 +201,7 @@ static void sym_chip_reset (hcb_p np)
  *  So, we need to abort the current operation prior to 
  *  soft resetting the chip.
  */
-static void sym_soft_reset (hcb_p np)
+static void sym_soft_reset (struct sym_hcb *np)
 {
 	u_char istat = 0;
 	int i;
@@ -234,12 +234,12 @@ do_chip_reset:
  *
  *  The interrupt handler will reinitialize the chip.
  */
-static void sym_start_reset(hcb_p np)
+static void sym_start_reset(struct sym_hcb *np)
 {
 	(void) sym_reset_scsi_bus(np, 1);
 }
  
-int sym_reset_scsi_bus(hcb_p np, int enab_int)
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int)
 {
 	u32 term;
 	int retv = 0;
@@ -293,7 +293,7 @@ out:
 /*
  *  Select SCSI clock frequency
  */
-static void sym_selectclock(hcb_p np, u_char scntl3)
+static void sym_selectclock(struct sym_hcb *np, u_char scntl3)
 {
 	/*
 	 *  If multiplier not present or not selected, leave here.
@@ -348,7 +348,7 @@ static void sym_selectclock(hcb_p np, u_
 /*
  *  calculate SCSI clock frequency (in KHz)
  */
-static unsigned getfreq (hcb_p np, int gen)
+static unsigned getfreq (struct sym_hcb *np, int gen)
 {
 	unsigned int ms = 0;
 	unsigned int f;
@@ -420,7 +420,7 @@ static unsigned getfreq (hcb_p np, int g
 	return f;
 }
 
-static unsigned sym_getfreq (hcb_p np)
+static unsigned sym_getfreq (struct sym_hcb *np)
 {
 	u_int f1, f2;
 	int gen = 8;
@@ -435,7 +435,7 @@ static unsigned sym_getfreq (hcb_p np)
 /*
  *  Get/probe chip SCSI clock frequency
  */
-static void sym_getclock (hcb_p np, int mult)
+static void sym_getclock (struct sym_hcb *np, int mult)
 {
 	unsigned char scntl3 = np->sv_scntl3;
 	unsigned char stest1 = np->sv_stest1;
@@ -492,7 +492,7 @@ static void sym_getclock (hcb_p np, int 
 /*
  *  Get/probe PCI clock frequency
  */
-static int sym_getpciclock (hcb_p np)
+static int sym_getpciclock (struct sym_hcb *np)
 {
 	int f = 0;
 
@@ -528,7 +528,7 @@ static u32 div_10M[] = {2*_5M, 3*_5M, 4*
  *  synchronous factor period.
  */
 static int 
-sym_getsync(hcb_p np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
+sym_getsync(struct sym_hcb *np, u_char dt, u_char sfac, u_char *divp, u_char *fakp)
 {
 	u32	clk = np->clock_khz;	/* SCSI clock frequency in kHz	*/
 	int	div = np->clock_divn;	/* Number of divisors supported	*/
@@ -648,7 +648,7 @@ sym_getsync(hcb_p np, u_char dt, u_char 
 /*
  *  Set initial io register bits from burst code.
  */
-static __inline void sym_init_burst(hcb_p np, u_char bc)
+static __inline void sym_init_burst(struct sym_hcb *np, u_char bc)
 {
 	np->rv_ctest4	&= ~0x80;
 	np->rv_dmode	&= ~(0x3 << 6);
@@ -668,7 +668,7 @@ static __inline void sym_init_burst(hcb_
 /*
  * Print out the list of targets that have some flag disabled by user.
  */
-static void sym_print_targets_flag(hcb_p np, int mask, char *msg)
+static void sym_print_targets_flag(struct sym_hcb *np, int mask, char *msg)
 {
 	int cnt;
 	int i;
@@ -696,7 +696,7 @@ static void sym_print_targets_flag(hcb_p
  *  is not safe on paper, but it seems to work quite 
  *  well. :)
  */
-static void sym_save_initial_setting (hcb_p np)
+static void sym_save_initial_setting (struct sym_hcb *np)
 {
 	np->sv_scntl0	= INB(nc_scntl0) & 0x0a;
 	np->sv_scntl3	= INB(nc_scntl3) & 0x07;
@@ -716,44 +716,11 @@ static void sym_save_initial_setting (hc
 		np->sv_ctest5	= INB(nc_ctest5) & 0x24;
 }
 
-#ifdef CONFIG_PARISC
-static u32 parisc_setup_hcb(hcb_p np, u32 period)
-{
-	unsigned long pdc_period;
-	char scsi_mode;
-	struct hardware_path hwpath;
-
-	/* Host firmware (PDC) keeps a table for crippling SCSI capabilities.
-	 * Many newer machines export one channel of 53c896 chip
-	 * as SE, 50-pin HD.  Also used for Multi-initiator SCSI clusters
-	 * to set the SCSI Initiator ID.
-	 */
-	get_pci_node_path(np->s.device, &hwpath);
-	if (!pdc_get_initiator(&hwpath, &np->myaddr, &pdc_period,
-				&np->maxwide, &scsi_mode))
-		return period;
-
-	if (scsi_mode >= 0) {
-		/* C3000 PDC reports period/mode */
-		SYM_SETUP_SCSI_DIFF = 0;
-		switch(scsi_mode) {
-		case 0:	np->scsi_mode = SMODE_SE; break;
-		case 1:	np->scsi_mode = SMODE_HVD; break;
-		case 2:	np->scsi_mode = SMODE_LVD; break;
-		default:	break;
-		}
-	}
-
-	return (u32) pdc_period;
-}
-#else
-static inline int parisc_setup_hcb(hcb_p np, u32 period) { return period; }
-#endif
 /*
  *  Prepare io register values used by sym_start_up() 
  *  according to selected and supported features.
  */
-static int sym_prepare_setting(hcb_p np, struct sym_nvram *nvram)
+static int sym_prepare_setting(struct sym_hcb *np, struct sym_nvram *nvram)
 {
 	u_char	burst_max;
 	u32	period;
@@ -816,8 +783,6 @@ static int sym_prepare_setting(hcb_p np,
 	 */
 	period = (4 * div_10M[0] + np->clock_khz - 1) / np->clock_khz;
 
-	period = parisc_setup_hcb(np, period);
-
 	if	(period <= 250)		np->minsync = 10;
 	else if	(period <= 303)		np->minsync = 11;
 	else if	(period <= 500)		np->minsync = 12;
@@ -1091,7 +1056,7 @@ static int sym_prepare_setting(hcb_p np,
  *  Has to be called with interrupts disabled.
  */
 #ifndef SYM_CONF_IOMAPPED
-static int sym_regtest (hcb_p np)
+static int sym_regtest (struct sym_hcb *np)
 {
 	register volatile u32 data;
 	/*
@@ -1115,7 +1080,7 @@ static int sym_regtest (hcb_p np)
 }
 #endif
 
-static int sym_snooptest (hcb_p np)
+static int sym_snooptest (struct sym_hcb *np)
 {
 	u32	sym_rd, sym_wr, sym_bk, host_rd, host_wr, pc, dstat;
 	int	i, err=0;
@@ -1241,7 +1206,7 @@ restart_test:
  *  First 24 register of the chip:
  *  	r0..rf
  */
-static void sym_log_hard_error(hcb_p np, u_short sist, u_char dstat)
+static void sym_log_hard_error(struct sym_hcb *np, u_short sist, u_char dstat)
 {
 	u32	dsp;
 	int	script_ofs;
@@ -1415,7 +1380,7 @@ sym_lookup_pci_chip_table (u_short devic
  *  This is only used if the direct mapping 
  *  has been unsuccessful.
  */
-int sym_lookup_dmap(hcb_p np, u32 h, int s)
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s)
 {
 	int i;
 
@@ -1448,7 +1413,7 @@ new:
  *  Update IO registers scratch C..R so they will be 
  *  in sync. with queued CCB expectations.
  */
-static void sym_update_dmap_regs(hcb_p np)
+static void sym_update_dmap_regs(struct sym_hcb *np)
 {
 	int o, i;
 
@@ -1503,6 +1468,7 @@ static void sym_check_goals(struct scsi_
 		if (st->period > np->maxsync_dt)
 			st->period = np->maxsync_dt;
 	} else {
+		st->options &= ~PPR_OPT_MASK;
 		if (st->offset > np->maxoffs)
 			st->offset = np->maxoffs;
 		if (st->period < np->minsync)
@@ -1510,7 +1476,7 @@ static void sym_check_goals(struct scsi_
 		if (st->period > np->maxsync)
 			st->period = np->maxsync;
 	}
-}		
+}
 
 /*
  *  Prepare the next negotiation message if needed.
@@ -1519,7 +1485,7 @@ static void sym_check_goals(struct scsi_
  *  negotiation and the nego_status field of the CCB.
  *  Returns the size of the message in bytes.
  */
-static int sym_prepare_nego(hcb_p np, ccb_p cp, int nego, u_char *msgptr)
+static int sym_prepare_nego(struct sym_hcb *np, ccb_p cp, int nego, u_char *msgptr)
 {
 	tcb_p tp = &np->target[cp->target];
 	int msglen = 0;
@@ -1575,7 +1541,7 @@ static int sym_prepare_nego(hcb_p np, cc
 		msgptr[msglen++] = 0;
 		msgptr[msglen++] = tp->tinfo.goal.offset;
 		msgptr[msglen++] = tp->tinfo.goal.width;
-		msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_DT;
+		msgptr[msglen++] = tp->tinfo.goal.options & PPR_OPT_MASK;
 		break;
 	};
 
@@ -1597,7 +1563,7 @@ static int sym_prepare_nego(hcb_p np, cc
 /*
  *  Insert a job into the start queue.
  */
-void sym_put_start_queue(hcb_p np, ccb_p cp)
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp)
 {
 	u_short	qidx;
 
@@ -1629,13 +1595,6 @@ void sym_put_start_queue(hcb_p np, ccb_p
 #endif
 
 	/*
-	 *  Optionnaly, set the IO timeout condition.
-	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	sym_timeout_ccb(np, cp, sym_cam_timeout(cp->cam_ccb));
-#endif
-
-	/*
 	 *  Insert first the idle task and then our job.
 	 *  The MBs should ensure proper ordering.
 	 */
@@ -1663,7 +1622,7 @@ void sym_put_start_queue(hcb_p np, ccb_p
 /*
  *  Start next ready-to-start CCBs.
  */
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn)
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn)
 {
 	SYM_QUEHEAD *qp;
 	ccb_p cp;
@@ -1717,7 +1676,7 @@ void sym_start_next_ccbs(hcb_p np, lcb_p
  *  prevent out of order LOADs by the CPU from having 
  *  prefetched stale data prior to DMA having occurred.
  */
-static int sym_wakeup_done (hcb_p np)
+static int sym_wakeup_done (struct sym_hcb *np)
 {
 	ccb_p cp;
 	int i, n;
@@ -1754,7 +1713,7 @@ static int sym_wakeup_done (hcb_p np)
  *  Complete all active CCBs with error.
  *  Used on CHIP/SCSI RESET.
  */
-static void sym_flush_busy_queue (hcb_p np, int cam_status)
+static void sym_flush_busy_queue (struct sym_hcb *np, int cam_status)
 {
 	/*
 	 *  Move all active CCBs to the COMP queue 
@@ -1773,7 +1732,7 @@ static void sym_flush_busy_queue (hcb_p 
  *     1: SCSI BUS RESET delivered or received.
  *     2: SCSI BUS MODE changed.
  */
-void sym_start_up (hcb_p np, int reason)
+void sym_start_up (struct sym_hcb *np, int reason)
 {
  	int	i;
 	u32	phys;
@@ -2009,7 +1968,7 @@ void sym_start_up (hcb_p np, int reason)
 /*
  *  Switch trans mode for current job and it's target.
  */
-static void sym_settrans(hcb_p np, int target, u_char dt, u_char ofs,
+static void sym_settrans(struct sym_hcb *np, int target, u_char opts, u_char ofs,
 			 u_char per, u_char wide, u_char div, u_char fak)
 {
 	SYM_QUEHEAD *qp;
@@ -2060,7 +2019,7 @@ static void sym_settrans(hcb_p np, int t
 	 */
 	if (np->features & FE_C10) {
 		uval = uval & ~(U3EN|AIPCKEN);
-		if (dt)	{
+		if (opts)	{
 			assert(np->features & FE_U3EN);
 			uval |= U3EN;
 		}
@@ -2118,7 +2077,7 @@ static void sym_settrans(hcb_p np, int t
  *  We received a WDTR.
  *  Let everything be aware of the changes.
  */
-static void sym_setwide(hcb_p np, int target, u_char wide)
+static void sym_setwide(struct sym_hcb *np, int target, u_char wide)
 {
 	tcb_p tp = &np->target[target];
 
@@ -2137,7 +2096,7 @@ static void sym_setwide(hcb_p np, int ta
  *  Let everything be aware of the changes.
  */
 static void
-sym_setsync(hcb_p np, int target,
+sym_setsync(struct sym_hcb *np, int target,
             u_char ofs, u_char per, u_char div, u_char fak)
 {
 	tcb_p tp = &np->target[target];
@@ -2163,17 +2122,17 @@ sym_setsync(hcb_p np, int target,
  *  Let everything be aware of the changes.
  */
 static void 
-sym_setpprot(hcb_p np, int target, u_char dt, u_char ofs,
+sym_setpprot(struct sym_hcb *np, int target, u_char opts, u_char ofs,
              u_char per, u_char wide, u_char div, u_char fak)
 {
 	tcb_p tp = &np->target[target];
 
-	sym_settrans(np, target, dt, ofs, per, wide, div, fak);
+	sym_settrans(np, target, opts, ofs, per, wide, div, fak);
 
 	tp->tinfo.goal.width	= tp->tinfo.curr.width  = wide;
 	tp->tinfo.goal.period	= tp->tinfo.curr.period = per;
 	tp->tinfo.goal.offset	= tp->tinfo.curr.offset = ofs;
-	tp->tinfo.goal.options	= tp->tinfo.curr.options = dt;
+	tp->tinfo.goal.options	= tp->tinfo.curr.options = opts;
 
 	sym_xpt_async_nego_ppr(np, target);
 }
@@ -2204,7 +2163,7 @@ sym_setpprot(hcb_p np, int target, u_cha
  *  pushes a DSA into a queue, we can trust it when it 
  *  points to a CCB.
  */
-static void sym_recover_scsi_int (hcb_p np, u_char hsts)
+static void sym_recover_scsi_int (struct sym_hcb *np, u_char hsts)
 {
 	u32	dsp	= INL (nc_dsp);
 	u32	dsa	= INL (nc_dsa);
@@ -2255,7 +2214,7 @@ reset_all:
 /*
  *  chip exception handler for selection timeout
  */
-static void sym_int_sto (hcb_p np)
+static void sym_int_sto (struct sym_hcb *np)
 {
 	u32 dsp	= INL (nc_dsp);
 
@@ -2270,7 +2229,7 @@ static void sym_int_sto (hcb_p np)
 /*
  *  chip exception handler for unexpected disconnect
  */
-static void sym_int_udc (hcb_p np)
+static void sym_int_udc (struct sym_hcb *np)
 {
 	printf ("%s: unexpected disconnect\n", sym_name(np));
 	sym_recover_scsi_int(np, HS_UNEXPECTED);
@@ -2286,7 +2245,7 @@ static void sym_int_udc (hcb_p np)
  *  mode to eight bit asynchronous, etc...
  *  So, just reinitializing all except chip should be enough.
  */
-static void sym_int_sbmc (hcb_p np)
+static void sym_int_sbmc (struct sym_hcb *np)
 {
 	u_char scsi_mode = INB (nc_stest4) & SMODE;
 
@@ -2327,7 +2286,7 @@ static void sym_int_sbmc (hcb_p np)
  *    The chip will load the DSP with the phase mismatch 
  *    JUMP address and interrupt the host processor.
  */
-static void sym_int_par (hcb_p np, u_short sist)
+static void sym_int_par (struct sym_hcb *np, u_short sist)
 {
 	u_char	hsts	= INB (HS_PRT);
 	u32	dsp	= INL (nc_dsp);
@@ -2415,7 +2374,7 @@ reset_all:
  *  We have to construct a new transfer descriptor,
  *  to transfer the rest of the current block.
  */
-static void sym_int_ma (hcb_p np)
+static void sym_int_ma (struct sym_hcb *np)
 {
 	u32	dbc;
 	u32	rest;
@@ -2734,7 +2693,7 @@ unexpected_phase:
 		if	(dsp == SCRIPTA_BA (np, send_ident)) {
 			if (cp->tag != NO_TAG && olen - rest <= 3) {
 				cp->host_status = HS_BUSY;
-				np->msgout[0] = M_IDENTIFY | cp->lun;
+				np->msgout[0] = IDENTIFY(0, cp->lun);
 				nxtdsp = SCRIPTB_BA (np, ident_break_atn);
 			}
 			else
@@ -2825,7 +2784,7 @@ reset_all:
  *  Use at your own decision and risk.
  */
 
-void sym_interrupt (hcb_p np)
+void sym_interrupt (struct sym_hcb *np)
 {
 	u_char	istat, istatc;
 	u_char	dstat;
@@ -2980,7 +2939,7 @@ unknown_int:
  *  It is called with SCRIPTS not running.
  */
 static int 
-sym_dequeue_from_squeue(hcb_p np, int i, int target, int lun, int task)
+sym_dequeue_from_squeue(struct sym_hcb *np, int i, int target, int lun, int task)
 {
 	int j;
 	ccb_p cp;
@@ -3037,13 +2996,13 @@ sym_dequeue_from_squeue(hcb_p np, int i,
  *  This function is called when all CCBs involved 
  *  in error handling/recovery have been reaped.
  */
-void sym_flush_comp_queue(hcb_p np, int cam_status)
+void sym_flush_comp_queue(struct sym_hcb *np, int cam_status)
 {
 	SYM_QUEHEAD *qp;
 	ccb_p cp;
 
 	while ((qp = sym_remque_head(&np->comp_ccbq)) != 0) {
-		cam_ccb_p ccb;
+		struct scsi_cmnd *ccb;
 		cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
 		sym_insque_tail(&cp->link_ccbq, &np->busy_ccbq);
 		/* Leave quiet CCBs waiting for resources */
@@ -3095,7 +3054,7 @@ void sym_flush_comp_queue(hcb_p np, int 
  *  SCRATCHA is assumed to have been loaded with STARTPOS 
  *  before the SCRIPTS called the C code.
  */
-static void sym_sir_bad_scsi_status(hcb_p np, int num, ccb_p cp)
+static void sym_sir_bad_scsi_status(struct sym_hcb *np, int num, ccb_p cp)
 {
 	tcb_p tp	= &np->target[cp->target];
 	u32		startp;
@@ -3163,10 +3122,7 @@ static void sym_sir_bad_scsi_status(hcb_
 		 *  requesting sense data.
 		 */
 
-		/*
-		 *  identify message
-		 */
-		cp->scsi_smsg2[0] = M_IDENTIFY | cp->lun;
+		cp->scsi_smsg2[0] = IDENTIFY(0, cp->lun);
 		msglen = 1;
 
 		/*
@@ -3215,7 +3171,7 @@ static void sym_sir_bad_scsi_status(hcb_
 		/*
 		 *  sense data
 		 */
-		bzero(cp->sns_bbuf, SYM_SNS_BBUF_LEN);
+		memset(cp->sns_bbuf, 0, SYM_SNS_BBUF_LEN);
 		cp->phys.sense.addr	= cpu_to_scr(vtobus(cp->sns_bbuf));
 		cp->phys.sense.size	= cpu_to_scr(SYM_SNS_BBUF_LEN);
 
@@ -3265,7 +3221,7 @@ static void sym_sir_bad_scsi_status(hcb_
  *  - lun=-1  means any logical UNIT otherwise a given one.
  *  - task=-1 means any task, otherwise a given one.
  */
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task)
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task)
 {
 	SYM_QUEHEAD qtmp, *qp;
 	int i = 0;
@@ -3284,7 +3240,7 @@ int sym_clear_tasks(hcb_p np, int cam_st
 	 *  the BUSY queue.
 	 */
 	while ((qp = sym_remque_head(&qtmp)) != 0) {
-		cam_ccb_p ccb;
+		struct scsi_cmnd *ccb;
 		cp = sym_que_entry(qp, struct sym_ccb, link_ccbq);
 		ccb = cp->cam_ccb;
 		if (cp->host_status != HS_DISCONNECT ||
@@ -3348,7 +3304,7 @@ printf("XXXX TASK @%p CLEARED\n", cp);
  *  all the CCBs that should have been aborted by the 
  *  target according to our message.
  */
-static void sym_sir_task_recovery(hcb_p np, int num)
+static void sym_sir_task_recovery(struct sym_hcb *np, int num)
 {
 	SYM_QUEHEAD *qp;
 	ccb_p cp;
@@ -3525,8 +3481,8 @@ static void sym_sir_task_recovery(hcb_p 
 		 */
 		if (lun != -1) {
 			lcb_p lp = sym_lp(np, tp, lun);
-			lp->to_clear = 0; /* We donnot expect to fail here */
-			np->abrt_msg[0] = M_IDENTIFY | lun;
+			lp->to_clear = 0; /* We don't expect to fail here */
+			np->abrt_msg[0] = IDENTIFY(0, lun);
 			np->abrt_msg[1] = M_ABORT;
 			np->abrt_tbl.size = 2;
 			break;
@@ -3567,7 +3523,7 @@ static void sym_sir_task_recovery(hcb_p 
 		 *  We have some task to abort.
 		 *  Set the IDENTIFY(lun)
 		 */
-		np->abrt_msg[0] = M_IDENTIFY | cp->lun;
+		np->abrt_msg[0] = IDENTIFY(0, cp->lun);
 
 		/*
 		 *  If we want to abort an untagged command, we 
@@ -3578,8 +3534,7 @@ static void sym_sir_task_recovery(hcb_p 
 		if (cp->tag == NO_TAG) {
 			np->abrt_msg[1] = M_ABORT;
 			np->abrt_tbl.size = 2;
-		}
-		else {
+		} else {
 			np->abrt_msg[1] = cp->scsi_smsg[1];
 			np->abrt_msg[2] = cp->scsi_smsg[2];
 			np->abrt_msg[3] = M_ABORT_TAG;
@@ -3701,7 +3656,7 @@ static void sym_sir_task_recovery(hcb_p 
  *  the corresponding values of dp_sg and dp_ofs.
  */
 
-static int sym_evaluate_dp(hcb_p np, ccb_p cp, u32 scr, int *ofs)
+static int sym_evaluate_dp(struct sym_hcb *np, ccb_p cp, u32 scr, int *ofs)
 {
 	u32	dp_scr;
 	int	dp_ofs, dp_sg, dp_sgmin;
@@ -3819,7 +3774,7 @@ out_err:
  *  is equivalent to a MODIFY DATA POINTER (offset=-1).
  */
 
-static void sym_modify_dp(hcb_p np, tcb_p tp, ccb_p cp, int ofs)
+static void sym_modify_dp(struct sym_hcb *np, tcb_p tp, ccb_p cp, int ofs)
 {
 	int dp_ofs	= ofs;
 	u32	dp_scr	= sym_get_script_dp (np, cp);
@@ -3918,7 +3873,7 @@ out_reject:
  *  a relevant information. :)
  */
 
-int sym_compute_residual(hcb_p np, ccb_p cp)
+int sym_compute_residual(struct sym_hcb *np, ccb_p cp)
 {
 	int dp_sg, dp_sgmin, resid = 0;
 	int dp_ofs = 0;
@@ -4018,7 +3973,7 @@ int sym_compute_residual(hcb_p np, ccb_p
  *  chip handler for SYNCHRONOUS DATA TRANSFER REQUEST (SDTR) message.
  */
 static int  
-sym_sync_nego_check(hcb_p np, int req, int target)
+sym_sync_nego_check(struct sym_hcb *np, int req, int target)
 {
 	u_char	chg, ofs, per, fak, div;
 
@@ -4099,7 +4054,7 @@ reject_it:
 	return -1;
 }
 
-static void sym_sync_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_sync_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	int req = 1;
 	int result;
@@ -4136,23 +4091,20 @@ reject_it:
  *  chip handler for PARALLEL PROTOCOL REQUEST (PPR) message.
  */
 static int 
-sym_ppr_nego_check(hcb_p np, int req, int target)
+sym_ppr_nego_check(struct sym_hcb *np, int req, int target)
 {
 	tcb_p tp = &np->target[target];
-	u_char	chg, ofs, per, fak, dt, div, wide;
+	unsigned char fak, div;
+	int dt, chg = 0;
+
+	unsigned char per = np->msgin[3];
+	unsigned char ofs = np->msgin[5];
+	unsigned char wide = np->msgin[6];
+	unsigned char opts = np->msgin[7] & PPR_OPT_MASK;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
 		sym_print_nego_msg(np, target, "ppr msgin", np->msgin);
-	};
-
-	/*
-	 *  Get requested values.
-	 */
-	chg  = 0;
-	per  = np->msgin[3];
-	ofs  = np->msgin[5];
-	wide = np->msgin[6];
-	dt   = np->msgin[7] & PPR_OPT_DT;
+	}
 
 	/*
 	 *  Check values against our limits.
@@ -4162,29 +4114,30 @@ sym_ppr_nego_check(hcb_p np, int req, in
 		wide = np->maxwide;
 	}
 	if (!wide || !(np->features & FE_ULTRA3))
-		dt &= ~PPR_OPT_DT;
+		opts = 0;
 
 	if (!(np->features & FE_U3EN))	/* Broken U3EN bit not supported */
-		dt &= ~PPR_OPT_DT;
+		opts = 0;
+
+	if (opts != (np->msgin[7] & PPR_OPT_MASK))
+		chg = 1;
 
-	if (dt != (np->msgin[7] & PPR_OPT_MASK)) chg = 1;
+	dt = opts & PPR_OPT_DT;
 
 	if (ofs) {
-		if (dt) {
-			if (ofs > np->maxoffs_dt)
-				{chg = 1; ofs = np->maxoffs_dt;}
+		unsigned char maxoffs = dt ? np->maxoffs_dt : np->maxoffs;
+		if (ofs > maxoffs) {
+			chg = 1;
+			ofs = maxoffs;
 		}
-		else if (ofs > np->maxoffs)
-			{chg = 1; ofs = np->maxoffs;}
 	}
 
 	if (ofs) {
-		if (dt) {
-			if (per < np->minsync_dt)
-				{chg = 1; per = np->minsync_dt;}
+		unsigned char minsync = dt ? np->minsync_dt : np->minsync;
+		if (per < np->minsync_dt) {
+			chg = 1;
+			per = minsync;
 		}
-		else if (per < np->minsync)
-			{chg = 1; per = np->minsync;}
 	}
 
 	/*
@@ -4204,7 +4157,7 @@ sym_ppr_nego_check(hcb_p np, int req, in
 	/*
 	 *  Apply new values.
 	 */
-	sym_setpprot (np, target, dt, ofs, per, wide, div, fak);
+	sym_setpprot(np, target, opts, ofs, per, wide, div, fak);
 
 	/*
 	 *  It was an answer. We are done.
@@ -4222,7 +4175,7 @@ sym_ppr_nego_check(hcb_p np, int req, in
 	np->msgout[4] = 0;
 	np->msgout[5] = ofs;
 	np->msgout[6] = wide;
-	np->msgout[7] = dt;
+	np->msgout[7] = opts;
 
 	if (DEBUG_FLAGS & DEBUG_NEGO) {
 		sym_print_nego_msg(np, target, "ppr msgout", np->msgout);
@@ -4238,7 +4191,7 @@ reject_it:
 	 *  If it is a device response that should result in  
 	 *  ST, we may want to try a legacy negotiation later.
 	 */
-	if (!req && !dt) {
+	if (!req && !opts) {
 		tp->tinfo.goal.options = 0;
 		tp->tinfo.goal.width   = wide;
 		tp->tinfo.goal.period  = per;
@@ -4247,7 +4200,7 @@ reject_it:
 	return -1;
 }
 
-static void sym_ppr_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_ppr_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	int req = 1;
 	int result;
@@ -4284,7 +4237,7 @@ reject_it:
  *  chip handler for WIDE DATA TRANSFER REQUEST (WDTR) message.
  */
 static int  
-sym_wide_nego_check(hcb_p np, int req, int target)
+sym_wide_nego_check(struct sym_hcb *np, int req, int target)
 {
 	u_char	chg, wide;
 
@@ -4349,7 +4302,7 @@ reject_it:
 	return -1;
 }
 
-static void sym_wide_nego(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_wide_nego(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	int req = 1;
 	int result;
@@ -4418,7 +4371,7 @@ reject_it:
  *  So, if a PPR makes problems, we may just want to 
  *  try a legacy negotiation later.
  */
-static void sym_nego_default(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_default(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	switch (cp->nego_status) {
 	case NS_PPR:
@@ -4448,7 +4401,7 @@ static void sym_nego_default(hcb_p np, t
  *  chip handler for MESSAGE REJECT received in response to 
  *  PPR, WIDE or SYNCHRONOUS negotiation.
  */
-static void sym_nego_rejected(hcb_p np, tcb_p tp, ccb_p cp)
+static void sym_nego_rejected(struct sym_hcb *np, tcb_p tp, ccb_p cp)
 {
 	sym_nego_default(np, tp, cp);
 	OUTB (HS_PRT, HS_BUSY);
@@ -4457,7 +4410,7 @@ static void sym_nego_rejected(hcb_p np, 
 /*
  *  chip exception handler for programmed interrupts.
  */
-static void sym_int_sir (hcb_p np)
+static void sym_int_sir (struct sym_hcb *np)
 {
 	u_char	num	= INB (nc_dsps);
 	u32	dsa	= INL (nc_dsa);
@@ -4731,7 +4684,7 @@ out_stuck:
 /*
  *  Acquire a control block
  */
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order)
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order)
 {
 	tcb_p tp = &np->target[tn];
 	lcb_p lp = sym_lp(np, tp, ln);
@@ -4880,7 +4833,7 @@ out_free:
 /*
  *  Release one control block
  */
-void sym_free_ccb (hcb_p np, ccb_p cp)
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp)
 {
 	tcb_p tp = &np->target[cp->target];
 	lcb_p lp = sym_lp(np, tp, cp->lun);
@@ -4965,13 +4918,6 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
 	sym_remque(&cp->link_ccbq);
 	sym_insque_head(&cp->link_ccbq, &np->free_ccbq);
 
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	/*
-	 *  Cancel any pending timeout condition.
-	 */
-	sym_untimeout_ccb(np, cp);
-#endif
-
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	if (lp) {
 		sym_remque(&cp->link2_ccbq);
@@ -4990,7 +4936,7 @@ void sym_free_ccb (hcb_p np, ccb_p cp)
 /*
  *  Allocate a CCB from memory and initialize its fixed part.
  */
-static ccb_p sym_alloc_ccb(hcb_p np)
+static ccb_p sym_alloc_ccb(struct sym_hcb *np)
 {
 	ccb_p cp = NULL;
 	int hcode;
@@ -5058,9 +5004,6 @@ static ccb_p sym_alloc_ccb(hcb_p np)
 	/*
 	 *  Chain into optionnal lists.
 	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-#endif
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	sym_insque_head(&cp->link2_ccbq, &np->dummy_ccbq);
 #endif
@@ -5077,7 +5020,7 @@ out_free:
 /*
  *  Look up a CCB from a DSA value.
  */
-static ccb_p sym_ccb_from_dsa(hcb_p np, u32 dsa)
+static ccb_p sym_ccb_from_dsa(struct sym_hcb *np, u32 dsa)
 {
 	int hcode;
 	ccb_p cp;
@@ -5097,7 +5040,7 @@ static ccb_p sym_ccb_from_dsa(hcb_p np, 
  *  Target control block initialisation.
  *  Nothing important to do at the moment.
  */
-static void sym_init_tcb (hcb_p np, u_char tn)
+static void sym_init_tcb (struct sym_hcb *np, u_char tn)
 {
 #if 0	/*  Hmmm... this checking looks paranoid. */
 	/*
@@ -5113,7 +5056,7 @@ static void sym_init_tcb (hcb_p np, u_ch
 /*
  *  Lun control block allocation and initialization.
  */
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln)
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln)
 {
 	tcb_p tp = &np->target[tn];
 	lcb_p lp = sym_lp(np, tp, ln);
@@ -5215,7 +5158,7 @@ fail:
 /*
  *  Allocate LCB resources for tagged command queuing.
  */
-static void sym_alloc_lcb_tags (hcb_p np, u_char tn, u_char ln)
+static void sym_alloc_lcb_tags (struct sym_hcb *np, u_char tn, u_char ln)
 {
 	tcb_p tp = &np->target[tn];
 	lcb_p lp = sym_lp(np, tp, ln);
@@ -5267,38 +5210,35 @@ fail:
 /*
  *  Queue a SCSI IO to the controller.
  */
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp)
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp)
 {
 	tcb_p	tp;
 	lcb_p	lp;
-	u_char	idmsg, *msgptr;
+	u_char	*msgptr;
 	u_int   msglen;
+	int can_disconnect;
 
 	/*
 	 *  Keep track of the IO in our CCB.
 	 */
-	cp->cam_ccb = (cam_ccb_p) csio;
+	cp->cam_ccb = csio;
 
 	/*
-	 *  Retreive the target descriptor.
+	 *  Retrieve the target descriptor.
 	 */
 	tp = &np->target[cp->target];
 
 	/*
-	 *  Retreive the lun descriptor.
+	 *  Retrieve the lun descriptor.
 	 */
 	lp = sym_lp(np, tp, cp->lun);
 
-	/*
-	 *  Build the IDENTIFY message.
-	 */
-	idmsg = M_IDENTIFY | cp->lun;
-	if (cp->tag != NO_TAG || (lp && (lp->curr_flags & SYM_DISC_ENABLED)))
-		idmsg |= 0x40;
+	can_disconnect = (cp->tag != NO_TAG) ||
+		(lp && (lp->curr_flags & SYM_DISC_ENABLED));
 
 	msgptr = cp->scsi_smsg;
 	msglen = 0;
-	msgptr[msglen++] = idmsg;
+	msgptr[msglen++] = IDENTIFY(can_disconnect, cp->lun);
 
 	/*
 	 *  Build the tag message if present.
@@ -5409,7 +5349,7 @@ int sym_queue_scsiio(hcb_p np, cam_scsii
 /*
  *  Reset a SCSI target (all LUNs of this target).
  */
-int sym_reset_scsi_target(hcb_p np, int target)
+int sym_reset_scsi_target(struct sym_hcb *np, int target)
 {
 	tcb_p tp;
 
@@ -5428,7 +5368,7 @@ int sym_reset_scsi_target(hcb_p np, int 
 /*
  *  Abort a SCSI IO.
  */
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out)
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out)
 {
 	/*
 	 *  Check that the IO is active.
@@ -5458,7 +5398,7 @@ int sym_abort_ccb(hcb_p np, ccb_p cp, in
 	return 0;
 }
 
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out)
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out)
 {
 	ccb_p cp;
 	SYM_QUEHEAD *qp;
@@ -5488,7 +5428,7 @@ int sym_abort_scsiio(hcb_p np, cam_ccb_p
  *  SCRATCHA is assumed to have been loaded with STARTPOS 
  *  before the SCRIPTS called the C code.
  */
-void sym_complete_error (hcb_p np, ccb_p cp)
+void sym_complete_error (struct sym_hcb *np, ccb_p cp)
 {
 	tcb_p tp;
 	lcb_p lp;
@@ -5622,11 +5562,11 @@ finish:
  *  The SCRIPTS processor is running while we are 
  *  completing successful commands.
  */
-void sym_complete_ok (hcb_p np, ccb_p cp)
+void sym_complete_ok (struct sym_hcb *np, ccb_p cp)
 {
 	tcb_p tp;
 	lcb_p lp;
-	cam_ccb_p ccb;
+	struct scsi_cmnd *ccb;
 	int resid;
 
 	/*
@@ -5732,7 +5672,7 @@ if (resid)
 /*
  *  Soft-attach the controller.
  */
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram)
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram)
 {
 	int i;
 
@@ -5823,17 +5763,9 @@ int sym_hcb_attach(hcb_p np, struct sym_
 	sym_que_init(&np->comp_ccbq);
 
 	/*
-	 *  Initializations for optional handling 
-	 *  of IO timeouts and device queueing.
+	 *  Initialization for optional handling 
+	 *  of device queueing.
 	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	sym_que_init(&np->tmo0_ccbq);
-	np->tmo_ccbq =
-		sym_calloc(2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
-			   "TMO_CCBQ");
-	for (i = 0 ; i < 2*SYM_CONF_TIMEOUT_ORDER_MAX ; i++)
-		sym_que_init(&np->tmo_ccbq[i]);
-#endif
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	sym_que_init(&np->dummy_ccbq);
 #endif
@@ -5965,7 +5897,7 @@ attach_failed:
 /*
  *  Free everything that has been allocated for this device.
  */
-void sym_hcb_free(hcb_p np)
+void sym_hcb_free(struct sym_hcb *np)
 {
 	SYM_QUEHEAD *qp;
 	ccb_p cp;
@@ -5979,12 +5911,6 @@ void sym_hcb_free(hcb_p np)
 		sym_mfree_dma(np->scriptb0, np->scriptb_sz, "SCRIPTB0");
 	if (np->scripta0)
 		sym_mfree_dma(np->scripta0, np->scripta_sz, "SCRIPTA0");
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	if (np->tmo_ccbq)
-		sym_mfree(np->tmo_ccbq,
-			  2*SYM_CONF_TIMEOUT_ORDER_MAX*sizeof(SYM_QUEHEAD),
-			  "TMO_CCBQ");
-#endif
 	if (np->squeue)
 		sym_mfree_dma(np->squeue, sizeof(u32)*(MAX_QUEUE*2), "SQUEUE");
 	if (np->dqueue)
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_hipd.h parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_hipd.h
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_hipd.h	Fri Oct 22 15:38:54 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_hipd.h	Wed Nov  3 06:19:09 2004
@@ -749,7 +749,7 @@ struct sym_ccb {
 	/*
 	 *  Pointer to CAM ccb and related stuff.
 	 */
-	cam_ccb_p cam_ccb;	/* CAM scsiio ccb		*/
+	struct scsi_cmnd *cam_ccb;	/* CAM scsiio ccb		*/
 	u8	cdb_buf[16];	/* Copy of CDB			*/
 	u8	*sns_bbuf;	/* Bounce buffer for sense data	*/
 #ifndef	SYM_SNS_BBUF_LEN
@@ -796,10 +796,6 @@ struct sym_ccb {
 	/*
 	 *  Other fields.
 	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	SYM_QUEHEAD tmo_linkq;	/* Optional timeout handling	*/
-	u_int	tmo_clock;	/* (link and dealine value)	*/
-#endif
 	u32	ccb_ba;		/* BUS address of this CCB	*/
 	u_short	tag;		/* Tag for this transfer	*/
 				/*  NO_TAG means no tag		*/
@@ -946,8 +942,8 @@ struct sym_hcb {
 	struct sym_fwa_ba fwa_bas;	/* Useful SCRIPTA bus addresses	*/
 	struct sym_fwb_ba fwb_bas;	/* Useful SCRIPTB bus addresses	*/
 	struct sym_fwz_ba fwz_bas;	/* Useful SCRIPTZ bus addresses	*/
-	void		(*fw_setup)(hcb_p np, struct sym_fw *fw);
-	void		(*fw_patch)(hcb_p np);
+	void		(*fw_setup)(struct sym_hcb *np, struct sym_fw *fw);
+	void		(*fw_patch)(struct sym_hcb *np);
 	char		*fw_name;
 
 	/*
@@ -1025,15 +1021,6 @@ struct sym_hcb {
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
 	SYM_QUEHEAD	dummy_ccbq;
 #endif
-	/*
-	 *  Optional handling of IO timeouts.
-	 */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-	SYM_QUEHEAD tmo0_ccbq;
-	SYM_QUEHEAD *tmo_ccbq;	/* [2*SYM_TIMEOUT_ORDER_MAX] */
-	u_int	tmo_clock;
-	u_int	tmo_actq;
-#endif
 
 	/*
 	 *  IMMEDIATE ARBITRATION (IARB) control.
@@ -1082,54 +1069,40 @@ struct sym_hcb {
  *  FIRMWARES (sym_fw.c)
  */
 struct sym_fw * sym_find_firmware(struct sym_pci_chip *chip);
-void sym_fw_bind_script (hcb_p np, u32 *start, int len);
+void sym_fw_bind_script (struct sym_hcb *np, u32 *start, int len);
 
 /*
  *  Driver methods called from O/S specific code.
  */
 char *sym_driver_name(void);
 void sym_print_xerr(ccb_p cp, int x_status);
-int sym_reset_scsi_bus(hcb_p np, int enab_int);
+int sym_reset_scsi_bus(struct sym_hcb *np, int enab_int);
 struct sym_pci_chip *
 sym_lookup_pci_chip_table (u_short device_id, u_char revision);
-void sym_put_start_queue(hcb_p np, ccb_p cp);
+void sym_put_start_queue(struct sym_hcb *np, ccb_p cp);
 #ifdef SYM_OPT_HANDLE_DEVICE_QUEUEING
-void sym_start_next_ccbs(hcb_p np, lcb_p lp, int maxn);
+void sym_start_next_ccbs(struct sym_hcb *np, lcb_p lp, int maxn);
 #endif
-void sym_start_up (hcb_p np, int reason);
-void sym_interrupt (hcb_p np);
-void sym_flush_comp_queue(hcb_p np, int cam_status);
-int sym_clear_tasks(hcb_p np, int cam_status, int target, int lun, int task);
-ccb_p sym_get_ccb (hcb_p np, u_char tn, u_char ln, u_char tag_order);
-void sym_free_ccb (hcb_p np, ccb_p cp);
-lcb_p sym_alloc_lcb (hcb_p np, u_char tn, u_char ln);
-int sym_queue_scsiio(hcb_p np, cam_scsiio_p csio, ccb_p cp);
-int sym_abort_scsiio(hcb_p np, cam_ccb_p ccb, int timed_out);
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-int sym_reset_scsi_target(hcb_p np, int target);
-void sym_hcb_free(hcb_p np);
-int sym_hcb_attach(hcb_p np, struct sym_fw *fw, struct sym_nvram *nvram);
-
-/*
- *  Optionnaly, the driver may handle IO timeouts.
- */
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-int sym_abort_ccb(hcb_p np, ccb_p cp, int timed_out);
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks);
-static void __inline sym_untimeout_ccb(hcb_p np, ccb_p cp)
-{
-	sym_remque(&cp->tmo_linkq);
-	sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-}
-void sym_clock(hcb_p np);
-#endif	/* SYM_OPT_HANDLE_IO_TIMEOUT */
+void sym_start_up (struct sym_hcb *np, int reason);
+void sym_interrupt (struct sym_hcb *np);
+void sym_flush_comp_queue(struct sym_hcb *np, int cam_status);
+int sym_clear_tasks(struct sym_hcb *np, int cam_status, int target, int lun, int task);
+ccb_p sym_get_ccb (struct sym_hcb *np, u_char tn, u_char ln, u_char tag_order);
+void sym_free_ccb (struct sym_hcb *np, ccb_p cp);
+lcb_p sym_alloc_lcb (struct sym_hcb *np, u_char tn, u_char ln);
+int sym_queue_scsiio(struct sym_hcb *np, struct scsi_cmnd *csio, ccb_p cp);
+int sym_abort_scsiio(struct sym_hcb *np, struct scsi_cmnd *ccb, int timed_out);
+int sym_abort_ccb(struct sym_hcb *np, ccb_p cp, int timed_out);
+int sym_reset_scsi_target(struct sym_hcb *np, int target);
+void sym_hcb_free(struct sym_hcb *np);
+int sym_hcb_attach(struct sym_hcb *np, struct sym_fw *fw, struct sym_nvram *nvram);
 
 /*
  *  Optionnaly, the driver may provide a function
  *  to announce transfer rate changes.
  */
 #ifdef	SYM_OPT_ANNOUNCE_TRANSFER_RATE
-void sym_announce_transfer_rate(hcb_p np, int target);
+void sym_announce_transfer_rate(struct sym_hcb *np, int target);
 #endif
 
 /*
@@ -1153,9 +1126,9 @@ do {									\
 	(data)->size = cpu_to_scr((((badd) >> 8) & 0xff000000) + len);	\
 } while (0)
 #elif SYM_CONF_DMA_ADDRESSING_MODE == 2
-int sym_lookup_dmap(hcb_p np, u32 h, int s);
+int sym_lookup_dmap(struct sym_hcb *np, u32 h, int s);
 static __inline void 
-sym_build_sge(hcb_p np, struct sym_tblmove *data, u64 badd, int len)
+sym_build_sge(struct sym_hcb *np, struct sym_tblmove *data, u64 badd, int len)
 {
 	u32 h = (badd>>32);
 	int s = (h&SYM_DMAP_MASK);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_malloc.c parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_malloc.c
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_malloc.c	Fri Oct 22 15:40:06 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_malloc.c	Wed Nov  3 06:19:09 2004
@@ -170,7 +170,7 @@ static void *__sym_calloc2(m_pool_p mp, 
 	}
 
 	if (p)
-		bzero(p, size);
+		memset(p, 0, size);
 	else if (uflags & SYM_MEM_WARN)
 		printf ("__sym_calloc2: failed to allocate %s[%d]\n", name, size);
 	return p;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_misc.c parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_misc.c
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_misc.c	Fri Oct 22 15:40:06 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_misc.c	Wed Nov  3 06:19:09 2004
@@ -37,109 +37,13 @@
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#ifdef __FreeBSD__
-#include <dev/sym/sym_glue.h>
-#else
 #include "sym_glue.h"
-#endif
-
-#ifdef	SYM_OPT_HANDLE_IO_TIMEOUT
-/*
- *  Optional CCB timeout handling.
- *
- *  This code is useful for O/Ses that allow or expect 
- *  SIMs (low-level drivers) to handle SCSI IO timeouts.
- *  It uses a power-of-two based algorithm of my own:) 
- *  that avoids scanning of lists, provided that:
- *
- *  - The IO does complete in less than half the associated
- *    timeout value.
- *  - The greatest delay between the queuing of the IO and 
- *    its completion is less than 
- *          (1<<(SYM_CONF_TIMEOUT_ORDER_MAX-1))/2 ticks.
- *
- *  For example, if tick is 1 second and the max order is 8,
- *  any IO that is completed within less than 64 seconds will 
- *  just be put into some list at queuing and be removed 
- *  at completion without any additionnal overhead.
- */
-
-/*
- *  Set a timeout condition on a CCB.
- */ 
-void sym_timeout_ccb(hcb_p np, ccb_p cp, u_int ticks)
-{
-	sym_remque(&cp->tmo_linkq);
-	cp->tmo_clock = np->tmo_clock + ticks;
-	if (!ticks) {
-		sym_insque_head(&cp->tmo_linkq, &np->tmo0_ccbq);
-	}
-	else {
-		int i = SYM_CONF_TIMEOUT_ORDER_MAX - 1;
-		while (i > 0) {
-			if (ticks >= (1<<(i+1)))
-				break;
-			--i;
-		}
-		if (!(np->tmo_actq & (1<<i)))
-			i += SYM_CONF_TIMEOUT_ORDER_MAX;
-		sym_insque_head(&cp->tmo_linkq, &np->tmo_ccbq[i]);
-	}
-}
-
-/*
- *  Walk a list of CCB and handle timeout conditions.
- *  Should never be called in normal situations.
- */
-static void sym_walk_ccb_tmo_list(hcb_p np, SYM_QUEHEAD *tmoq)
-{
-	SYM_QUEHEAD qtmp, *qp;
-	ccb_p cp;
-
-	sym_que_move(tmoq, &qtmp);
-	while ((qp = sym_remque_head(&qtmp)) != 0) {
-		sym_insque_head(qp, &np->tmo0_ccbq);
-		cp = sym_que_entry(qp, struct sym_ccb, tmo_linkq);
-		if (cp->tmo_clock     != np->tmo_clock &&
-		    cp->tmo_clock + 1 != np->tmo_clock)
-			sym_timeout_ccb(np, cp, cp->tmo_clock - np->tmo_clock);
-		else
-			sym_abort_ccb(np, cp, 1);
-	}
-}
-
-/*
- * Our clock handler called from the O/S specific side.
- */
-void sym_clock(hcb_p np)
-{
-	int i, j;
-	u_int tmp;
-
-	tmp = np->tmo_clock;
-	tmp ^= (++np->tmo_clock);
-
-	for (i = 0; i < SYM_CONF_TIMEOUT_ORDER_MAX; i++, tmp >>= 1) {
-		if (!(tmp & 1))
-			continue;
-		j = i;
-		if (np->tmo_actq & (1<<i))
-			j += SYM_CONF_TIMEOUT_ORDER_MAX;
-
-		if (!sym_que_empty(&np->tmo_ccbq[j])) {
-			sym_walk_ccb_tmo_list(np, &np->tmo_ccbq[j]);
-		}
-		np->tmo_actq ^= (1<<i);
-	}
-}
-#endif	/* SYM_OPT_HANDLE_IO_TIMEOUT */
-
 
 #ifdef	SYM_OPT_ANNOUNCE_TRANSFER_RATE
 /*
  *  Announce transfer rate if anything changed since last announcement.
  */
-void sym_announce_transfer_rate(hcb_p np, int target)
+void sym_announce_transfer_rate(struct sym_hcb *np, int target)
 {
 	tcb_p tp = &np->target[target];
 
@@ -190,10 +94,12 @@ void sym_announce_transfer_rate(hcb_p np
 			mb10 = (f10 + period/2) / period;
 		}
 		printf_info (
-		    "%s:%d: %s %sSCSI %d.%d MB/s %s (%d.%d ns, offset %d)\n",
+		    "%s:%d: %s %sSCSI %d.%d MB/s %s%s%s (%d.%d ns, offset %d)\n",
 		    sym_name(np), target, scsi, __tcurr.width? "WIDE " : "",
 		    mb10/10, mb10%10,
 		    (__tcurr.options & PPR_OPT_DT) ? "DT" : "ST",
+		    (__tcurr.options & PPR_OPT_IU) ? " IU" : "",
+		    (__tcurr.options & PPR_OPT_QAS) ? " QAS" : "",
 		    period/10, period%10, __tcurr.offset);
 	}
 	else
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_nvram.c parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_nvram.c
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_nvram.c	Fri Oct 22 15:39:43 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_nvram.c	Wed Nov  3 06:19:09 2004
@@ -68,6 +68,21 @@ void sym_nvram_setup_host(struct sym_hcb
 	case SYM_TEKRAM_NVRAM:
 		np->myaddr = nvram->data.Tekram.host_id & 0x0f;
 		break;
+#ifdef CONFIG_PARISC
+	case SYM_PARISC_PDC:
+		if (nvram->data.parisc.host_id != -1)
+			np->myaddr = nvram->data.parisc.host_id;
+		if (nvram->data.parisc.factor != -1)
+			np->minsync = nvram->data.parisc.factor;
+		if (nvram->data.parisc.width != -1)
+			np->maxwide = nvram->data.parisc.width;
+		switch (nvram->data.parisc.mode) {
+			case 0: np->scsi_mode = SMODE_SE; break;
+			case 1: np->scsi_mode = SMODE_HVD; break;
+			case 2: np->scsi_mode = SMODE_LVD; break;
+			default: break;
+		}
+#endif
 	default:
 		break;
 	}
@@ -702,6 +717,28 @@ static int sym_read_Tekram_nvram (struct
 	return 0;
 }
 
+#ifdef CONFIG_PARISC
+/*
+ * Host firmware (PDC) keeps a table for altering SCSI capabilities.
+ * Many newer machines export one channel of 53c896 chip as SE, 50-pin HD.
+ * Also used for Multi-initiator SCSI clusters to set the SCSI Initiator ID.
+ */
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *pdc)
+{
+	struct hardware_path hwpath;
+	get_pci_node_path(np->pdev, &hwpath);
+	if (!pdc_get_initiator(&hwpath, pdc))
+		return 0;
+
+	return SYM_PARISC_PDC;
+}
+#else
+static int sym_read_parisc_pdc(struct sym_device *np, struct pdc_initiator *x)
+{
+	return 0;
+}
+#endif
+
 /*
  *  Try reading Symbios or Tekram NVRAM
  */
@@ -714,7 +751,7 @@ int sym_read_nvram(struct sym_device *np
 		nvp->type = SYM_TEKRAM_NVRAM;
 		sym_display_Tekram_nvram(np, &nvp->data.Tekram);
 	} else {
-		nvp->type = 0;
+		nvp->type = sym_read_parisc_pdc(np, &nvp->data.parisc);
 	}
 	return nvp->type;
 }
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_nvram.h parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_nvram.h
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_2/sym_nvram.h	Fri Oct 22 15:40:06 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_2/sym_nvram.h	Wed Nov  3 06:19:09 2004
@@ -171,6 +171,10 @@ struct Tekram_nvram {
 typedef struct Tekram_nvram	Tekram_nvram;
 typedef struct Tekram_target	Tekram_target;
 
+#ifndef CONFIG_PARISC
+struct pdc_initiator { int dummy; };
+#endif
+
 /*
  *  Union of supported NVRAM formats.
  */
@@ -178,10 +182,12 @@ struct sym_nvram {
 	int type;
 #define	SYM_SYMBIOS_NVRAM	(1)
 #define	SYM_TEKRAM_NVRAM	(2)
+#define SYM_PARISC_PDC		(3)
 #if SYM_CONF_NVRAM_SUPPORT
 	union {
 		Symbios_nvram Symbios;
 		Tekram_nvram Tekram;
+		struct pdc_initiator parisc;
 	} data;
 #endif
 };
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_comm.h parisc-2.6-bk/drivers/scsi/sym53c8xx_comm.h
--- linux-2.6.10-rc1-bk13/drivers/scsi/sym53c8xx_comm.h	Fri Oct 22 15:39:40 2004
+++ parisc-2.6-bk/drivers/scsi/sym53c8xx_comm.h	Wed Nov  3 06:19:08 2004
@@ -505,8 +505,6 @@ static int __map_scsi_sg_data(struct dev
 #define unmap_scsi_data(np, cmd)	__unmap_scsi_data(np->dev, cmd)
 #define map_scsi_single_data(np, cmd)	__map_scsi_single_data(np->dev, cmd)
 #define map_scsi_sg_data(np, cmd)	__map_scsi_sg_data(np->dev, cmd)
-#define sync_scsi_data_for_cpu(np, cmd)	__sync_scsi_data_for_cpu(np->dev, cmd)
-#define sync_scsi_data_for_device(np, cmd) __sync_scsi_data_for_device(np->dev, cmd)
 
 /*==========================================================
 **
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/serial/8250.c parisc-2.6-bk/drivers/serial/8250.c
--- linux-2.6.10-rc1-bk13/drivers/serial/8250.c	Wed Nov  3 05:57:47 2004
+++ parisc-2.6-bk/drivers/serial/8250.c	Wed Nov  3 06:19:11 2004
@@ -2110,13 +2110,20 @@ static struct console serial8250_console
 	.data		= &serial8250_reg,
 };
 
-static int __init serial8250_console_init(void)
+int __init serial8250_console_init(void)
 {
+	static int serial8250_console_initialised;
+	if (serial8250_console_initialised)
+		return 0;
+	serial8250_console_initialised = 1;
+
 	serial8250_isa_init_ports();
 	register_console(&serial8250_console);
 	return 0;
 }
+#ifndef __hppa__
 console_initcall(serial8250_console_init);
+#endif
 
 static int __init serial8250_late_console_init(void)
 {
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/serial/8250_gsc.c parisc-2.6-bk/drivers/serial/8250_gsc.c
--- linux-2.6.10-rc1-bk13/drivers/serial/8250_gsc.c	Wed Nov  3 05:57:47 2004
+++ parisc-2.6-bk/drivers/serial/8250_gsc.c	Wed Nov  3 06:29:29 2004
@@ -40,7 +40,7 @@ serial_init_chip(struct parisc_device *d
 		 * what we have here is a missing parent device, so tell
 		 * the user what they're missing.
 		 */
-		if (dev->parent->id.hw_type != HPHW_IOA) {
+		if (parisc_parent(dev)->id.hw_type != HPHW_IOA) {
 			printk(KERN_INFO "Serial: device 0x%lx not configured.\n"
 				"Enable support for Wax, Lasi, Asp or Dino.\n", dev->hpa);
 		}
@@ -65,7 +65,7 @@ serial_init_chip(struct parisc_device *d
 		printk(KERN_WARNING "serial8250_register_port returned error %d\n", err);
 		return err;
 	}
-
+        
 	return 0;
 }
 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/serial/8250_pci.c parisc-2.6-bk/drivers/serial/8250_pci.c
--- linux-2.6.10-rc1-bk13/drivers/serial/8250_pci.c	Wed Nov  3 05:57:47 2004
+++ parisc-2.6-bk/drivers/serial/8250_pci.c	Wed Nov  3 06:19:11 2004
@@ -2234,7 +2234,14 @@ static struct pci_driver serial_pci_driv
 
 static int __init serial8250_pci_init(void)
 {
-	return pci_module_init(&serial_pci_driver);
+	int ret;
+	ret = pci_module_init(&serial_pci_driver);
+
+#if defined(__hppa__) && defined(CONFIG_SERIAL_8250_CONSOLE)
+	serial8250_console_init();
+#endif
+
+	return ret;
 }
 
 static void __exit serial8250_pci_exit(void)
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/drivers/serial/serial_core.c parisc-2.6-bk/drivers/serial/serial_core.c
--- linux-2.6.10-rc1-bk13/drivers/serial/serial_core.c	Wed Nov  3 05:57:47 2004
+++ parisc-2.6-bk/drivers/serial/serial_core.c	Wed Nov  3 06:19:11 2004
@@ -229,7 +229,8 @@ static void uart_shutdown(struct uart_st
 	/*
 	 * Ensure that the IRQ handler isn't running on another CPU.
 	 */
-	synchronize_irq(port->irq);
+	if (port->irq != SERIAL_IRQ_NONE)
+		synchronize_irq(port->irq);
 
 	/*
 	 * Free the transmit buffer page.
@@ -1911,7 +1912,11 @@ uart_report_port(struct uart_driver *drv
 		printk("MMIO 0x%lx", port->mapbase);
 		break;
 	}
-	printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
+	if (port->irq == SERIAL_IRQ_NONE) {
+		printk(" (polled) is a %s\n", uart_type(port));
+	} else {
+		printk(" (irq = %d) is a %s\n", port->irq, uart_type(port));
+	}
 }
 
 static void
@@ -2169,9 +2174,14 @@ int uart_add_one_port(struct uart_driver
 	 * successfully registered yet, try to re-register it.
 	 * It may be that the port was not available.
 	 */
+#ifndef __hppa__
+	/* HPPA can't register this here.  If it does, we get it registered
+	 * again in the initialisation routine and a loop results in the
+	 * list of consoles */
 	if (port->type != PORT_UNKNOWN &&
 	    port->cons && !(port->cons->flags & CON_ENABLED))
 		register_console(port->cons);
+#endif
 
  out:
 	up(&port_sem);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/fs/compat.c parisc-2.6-bk/fs/compat.c
--- linux-2.6.10-rc1-bk13/fs/compat.c	Fri Oct 22 15:39:07 2004
+++ parisc-2.6-bk/fs/compat.c	Wed Nov  3 06:19:13 2004
@@ -205,7 +205,7 @@ static int put_compat_statfs64(struct co
 	return 0;
 }
 
-asmlinkage long compat_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf)
+asmlinkage long compat_sys_statfs64(const char __user *path, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
 	struct nameidata nd;
 	int error;
@@ -224,7 +224,7 @@ asmlinkage long compat_statfs64(const ch
 	return error;
 }
 
-asmlinkage long compat_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
+asmlinkage long compat_sys_fstatfs64(unsigned int fd, compat_size_t sz, struct compat_statfs64 __user *buf)
 {
 	struct file * file;
 	struct kstatfs tmp;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/fs/smbfs/inode.c parisc-2.6-bk/fs/smbfs/inode.c
--- linux-2.6.10-rc1-bk13/fs/smbfs/inode.c	Fri Oct 22 15:38:36 2004
+++ parisc-2.6-bk/fs/smbfs/inode.c	Wed Nov  3 06:19:14 2004
@@ -563,6 +563,7 @@ int smb_fill_super(struct super_block *s
 
 	mnt->ttl = SMB_TTL_DEFAULT;
 	if (ver == SMB_MOUNT_OLDVERSION) {
+#ifdef CONFIG_UID16
 		mnt->version = oldmnt->version;
 
 		SET_UID(mnt->uid, oldmnt->uid);
@@ -573,6 +574,9 @@ int smb_fill_super(struct super_block *s
 
 		mnt->flags = (oldmnt->file_mode >> 9) | SMB_MOUNT_UID |
 			SMB_MOUNT_GID | SMB_MOUNT_FMODE | SMB_MOUNT_DMODE;
+#else
+		goto out_bad_option;
+#endif
 	} else {
 		mnt->file_mode = mnt->dir_mode = S_IRWXU | S_IRGRP | S_IXGRP |
 						S_IROTH | S_IXOTH | S_IFREG;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-generic/compat_signal.h parisc-2.6-bk/include/asm-generic/compat_signal.h
--- linux-2.6.10-rc1-bk13/include/asm-generic/compat_signal.h	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/include/asm-generic/compat_signal.h	Wed Nov  3 06:12:45 2004
@@ -0,0 +1,25 @@
+#ifndef _ASM_GENERIC_COMPAT_SIGNAL_H
+#define _ASM_GENERIC_COMPAT_SIGNAL_H
+
+#ifndef __ASSEMBLY__
+#include <linux/compat.h>
+
+typedef compat_uptr_t compat_sighandler_t;
+
+typedef struct compat_sigaltstack {
+	compat_uptr_t ss_sp;
+	compat_int_t ss_flags;
+	compat_size_t ss_size;
+} compat_stack_t;
+
+/* Most things should be clean enough to redefine this at will, if care
+   is taken to make libc match.  */
+
+struct compat_sigaction {
+	compat_sighandler_t sa_handler;
+	compat_uint_t sa_flags;
+	compat_sigset_t sa_mask;		/* mask last for extensibility */
+};
+
+#endif /* !__ASSEMBLY__ */
+#endif /* !_ASM_GENERIC_COMPAT_SIGNAL_H */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-generic/siginfo.h parisc-2.6-bk/include/asm-generic/siginfo.h
--- linux-2.6.10-rc1-bk13/include/asm-generic/siginfo.h	Fri Oct 22 15:38:54 2004
+++ parisc-2.6-bk/include/asm-generic/siginfo.h	Wed Nov  3 06:19:16 2004
@@ -240,9 +240,13 @@ typedef struct siginfo {
 #define SIGEV_THREAD	2	/* deliver via thread creation */
 #define SIGEV_THREAD_ID 4	/* deliver to thread */
 
+#ifndef __ARCH_SIGEV_PREAMBLE_SIZE
+#define __ARCH_SIGEV_PREAMBLE_SIZE (sizeof(int) * 2 + sizeof(sigval_t))
+#endif
+
 #define SIGEV_MAX_SIZE	64
 #ifndef SIGEV_PAD_SIZE
-#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE/sizeof(int)) - 3)
+#define SIGEV_PAD_SIZE	((SIGEV_MAX_SIZE - __ARCH_SIGEV_PREAMBLE_SIZE)/sizeof(int))
 #endif
 
 #ifndef HAVE_ARCH_SIGEVENT_T
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-generic/vmlinux.lds.h parisc-2.6-bk/include/asm-generic/vmlinux.lds.h
--- linux-2.6.10-rc1-bk13/include/asm-generic/vmlinux.lds.h	Fri Oct 22 15:38:16 2004
+++ parisc-2.6-bk/include/asm-generic/vmlinux.lds.h	Wed Nov  3 06:19:16 2004
@@ -18,6 +18,9 @@
 									\
 	/* PCI quirks */						\
 	.pci_fixup        : AT(ADDR(.pci_fixup) - LOAD_OFFSET) {	\
+		VMLINUX_SYMBOL(__start_pci_fixups_early) = .;		\
+		*(.pci_fixup_early)					\
+		VMLINUX_SYMBOL(__end_pci_fixups_early) = .;		\
 		VMLINUX_SYMBOL(__start_pci_fixups_header) = .;		\
 		*(.pci_fixup_header)					\
 		VMLINUX_SYMBOL(__end_pci_fixups_header) = .;		\
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-ia64/compat.h parisc-2.6-bk/include/asm-ia64/compat.h
--- linux-2.6.10-rc1-bk13/include/asm-ia64/compat.h	Fri Oct 22 15:40:28 2004
+++ parisc-2.6-bk/include/asm-ia64/compat.h	Wed Nov  3 06:19:17 2004
@@ -15,6 +15,9 @@ typedef s32		compat_key_t;
 typedef s32		compat_pid_t;
 typedef u16		compat_uid_t;
 typedef u16		compat_gid_t;
+/* Define for use in compat_siginfo_t */
+#undef __ARCH_SI_COMPAT_UID_T
+#define __ARCH_SI_COMPAT_UID_T	compat_uid32_t
 typedef u32		compat_uid32_t;
 typedef u32		compat_gid32_t;
 typedef u16		compat_mode_t;
@@ -27,6 +30,7 @@ typedef u16		compat_ipc_pid_t;
 typedef s32		compat_daddr_t;
 typedef u32		compat_caddr_t;
 typedef __kernel_fsid_t	compat_fsid_t;
+typedef s32		compat_timer_t;
 
 typedef s32		compat_int_t;
 typedef s32		compat_long_t;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-parisc/dma-mapping.h parisc-2.6-bk/include/asm-parisc/dma-mapping.h
--- linux-2.6.10-rc1-bk13/include/asm-parisc/dma-mapping.h	Fri Oct 22 15:39:06 2004
+++ parisc-2.6-bk/include/asm-parisc/dma-mapping.h	Wed Nov  3 06:19:18 2004
@@ -1,8 +1,8 @@
 #ifndef _PARISC_DMA_MAPPING_H
 #define _PARISC_DMA_MAPPING_H
 
-#include <linux/mm.h>
 #include <linux/config.h>
+#include <linux/mm.h>
 #include <asm/cacheflush.h>
 #include <asm/scatterlist.h>
 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-parisc/hardware.h parisc-2.6-bk/include/asm-parisc/hardware.h
--- linux-2.6.10-rc1-bk13/include/asm-parisc/hardware.h	Fri Oct 22 15:39:50 2004
+++ parisc-2.6-bk/include/asm-parisc/hardware.h	Wed Nov  3 06:19:18 2004
@@ -117,12 +117,13 @@ extern int unregister_parisc_driver(stru
 extern void walk_central_bus(void);
 extern void fixup_child_irqs(struct parisc_device *parent, int irqbase,
 		int (*choose)(struct parisc_device *parent));
-extern void print_subdevices(struct parisc_device *dev);
 extern const struct parisc_device *find_pa_parent_type(const struct parisc_device *, int);
 extern void print_parisc_devices(void);
 extern char *print_pa_hwpath(struct parisc_device *dev, char *path);
 extern char *print_pci_hwpath(struct pci_dev *dev, char *path);
 extern void get_pci_node_path(struct pci_dev *dev, struct hardware_path *path);
+extern void init_parisc_bus(void);
+extern struct device *hwpath_to_device(struct hardware_path *modpath);
 
 
 /* inventory.c: */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-parisc/io.h parisc-2.6-bk/include/asm-parisc/io.h
--- linux-2.6.10-rc1-bk13/include/asm-parisc/io.h	Wed Nov  3 05:57:50 2004
+++ parisc-2.6-bk/include/asm-parisc/io.h	Wed Nov  3 06:30:03 2004
@@ -1,14 +1,6 @@
 #ifndef _ASM_IO_H
 #define _ASM_IO_H
 
-/* USE_HPPA_IOREMAP IS THE MAGIC FLAG TO ENABLE OR DISABLE REAL IOREMAP() FUNCTIONALITY */
-/* FOR 712 or 715 MACHINES THIS SHOULD BE ENABLED, 
-   NEWER MACHINES STILL HAVE SOME ISSUES IN THE SCSI AND/OR NETWORK DRIVERS AND 
-   BECAUSE OF THAT I WILL LEAVE IT DISABLED FOR NOW <deller@gmx.de> */
-/* WHEN THOSE ISSUES ARE SOLVED, USE_HPPA_IOREMAP WILL GO AWAY */
-#define USE_HPPA_IOREMAP 0
-
-
 #include <linux/config.h>
 #include <linux/types.h>
 #include <asm/pgtable.h>
@@ -26,32 +18,11 @@ extern unsigned long parisc_vmerge_max_s
 
 /* Memory mapped IO */
 
-extern void * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
-
-extern inline void * ioremap(unsigned long offset, unsigned long size)
-{
-	return __ioremap(offset, size, 0);
-}
-
-/*
- * This one maps high address device memory and turns off caching for that area.
- * it's useful if some control registers are in such an area and write combining
- * or read caching is not desirable:
- */
-extern inline void * ioremap_nocache(unsigned long offset, unsigned long size)
-{
-        return __ioremap(offset, size, _PAGE_NO_CACHE /* _PAGE_PCD */);
-}
-
-extern void iounmap(void *addr);
-
-/*
- * __raw_ variants have no defined meaning.  on hppa, it means `i was
- * too lazy to ioremap first'.  kind of like isa_, except that there's
- * no additional base address to add on.
+/* 
+ * These functions support PA-RISC drivers which don't yet call ioremap().
+ * They will disappear once the last of these drivers is gone.
  */
-#define __raw_readb(a) ___raw_readb((unsigned long)(a))
-extern __inline__ unsigned char ___raw_readb(unsigned long addr)
+static inline unsigned char gsc_readb(volatile void __iomem *addr)
 {
 	long flags;
 	unsigned char ret;
@@ -65,8 +36,7 @@ extern __inline__ unsigned char ___raw_r
 	return ret;
 }
 
-#define __raw_readw(a) ___raw_readw((unsigned long)(a))
-extern __inline__ unsigned short ___raw_readw(unsigned long addr)
+static inline unsigned short gsc_readw(volatile void __iomem *addr)
 {
 	long flags;
 	unsigned short ret;
@@ -80,8 +50,7 @@ extern __inline__ unsigned short ___raw_
 	return ret;
 }
 
-#define __raw_readl(a) ___raw_readl((unsigned long)(a))
-extern __inline__ unsigned int ___raw_readl(unsigned long addr)
+static inline unsigned int gsc_readl(volatile void __iomem *addr)
 {
 	u32 ret;
 
@@ -92,8 +61,7 @@ extern __inline__ unsigned int ___raw_re
 	return ret;
 }
 
-#define __raw_readq(a) ___raw_readq((unsigned long)(a))
-extern __inline__ unsigned long long ___raw_readq(unsigned long addr)
+static inline unsigned long long gsc_readq(volatile void __iomem *addr)
 {
 	unsigned long long ret;
 #ifdef __LP64__
@@ -102,14 +70,13 @@ extern __inline__ unsigned long long ___
 	:  "=r" (ret) : "r" (addr) );
 #else
 	/* two reads may have side effects.. */
-	ret = ((u64) __raw_readl(addr)) << 32;
-	ret |= __raw_readl(addr+4);
+	ret = ((u64) gsc_readl(addr)) << 32;
+	ret |= gsc_readl(addr+4);
 #endif
 	return ret;
 }
 
-#define __raw_writeb(a,b) ___raw_writeb(a, (unsigned long)(b))
-extern __inline__ void ___raw_writeb(unsigned char val, unsigned long addr)
+static inline void gsc_writeb(unsigned char val, volatile void __iomem *addr)
 {
 	long flags;
 	__asm__ __volatile__(
@@ -119,8 +86,7 @@ extern __inline__ void ___raw_writeb(uns
 	: "=&r" (flags) :  "r" (val), "r" (addr) );
 }
 
-#define __raw_writew(a,b) ___raw_writew(a, (unsigned long)(b))
-extern __inline__ void ___raw_writew(unsigned short val, unsigned long addr)
+static inline void gsc_writew(unsigned short val, volatile void __iomem *addr)
 {
 	long flags;
 	__asm__ __volatile__(
@@ -130,16 +96,14 @@ extern __inline__ void ___raw_writew(uns
 	: "=&r" (flags) :  "r" (val), "r" (addr) );
 }
 
-#define __raw_writel(a,b) ___raw_writel(a, (unsigned long)(b))
-extern __inline__ void ___raw_writel(unsigned int val, unsigned long addr)
+static inline void gsc_writel(unsigned int val, volatile void __iomem *addr)
 {
 	__asm__ __volatile__(
 	"	stwas	%0,0(%1)\n"
 	: :  "r" (val), "r" (addr) );
 }
 
-#define __raw_writeq(a,b) ___raw_writeq(a, (unsigned long)(b))
-extern __inline__ void ___raw_writeq(unsigned long long val, unsigned long addr)
+static inline void gsc_writeq(unsigned long long val, volatile void __iomem *addr)
 {
 #ifdef __LP64__
 	__asm__ __volatile__(
@@ -147,45 +111,105 @@ extern __inline__ void ___raw_writeq(uns
 	: :  "r" (val), "r" (addr) );
 #else
 	/* two writes may have side effects.. */
-	__raw_writel(val >> 32, addr);
-	__raw_writel(val, addr+4);
+	gsc_writel(val >> 32, addr);
+	gsc_writel(val, addr+4);
 #endif
 }
 
+/*
+ * The standard PCI ioremap interfaces
+ */
+
+extern void __iomem * __ioremap(unsigned long offset, unsigned long size, unsigned long flags);
+
+extern inline void __iomem * ioremap(unsigned long offset, unsigned long size)
+{
+	return __ioremap(offset, size, 0);
+}
+
+/*
+ * This one maps high address device memory and turns off caching for that area.
+ * it's useful if some control registers are in such an area and write combining
+ * or read caching is not desirable:
+ */
+extern inline void * ioremap_nocache(unsigned long offset, unsigned long size)
+{
+        return __ioremap(offset, size, _PAGE_NO_CACHE /* _PAGE_PCD */);
+}
+
+extern void iounmap(void __iomem *addr);
+
+/*
+ * USE_HPPA_IOREMAP is the magic flag to enable or disable real ioremap()
+ * functionality.  It's currently disabled because it may not work on some
+ * machines.
+ */
+#define USE_HPPA_IOREMAP 0
+
 #if USE_HPPA_IOREMAP
-#define readb(addr) (*(volatile unsigned char *) (addr))
-#define readw(addr) (*(volatile unsigned short *) (addr))
-#define readl(addr) (*(volatile unsigned int *) (addr))
-#define readq(addr) (*(volatile u64 *) (addr))
-#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
-#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
-#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
-#define writeq(b,addr) (*(volatile u64 *) (addr) = (b))
+static inline unsigned char __raw_readb(const volatile void __iomem *addr)
+{
+	return (*(volatile unsigned char __force *) (addr));
+}
+static inline unsigned short __raw_readw(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned short __force *) addr;
+}
+static inline unsigned int __raw_readl(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned int __force *) addr;
+}
+static inline unsigned long long __raw_readq(const volatile void __iomem *addr)
+{
+	return *(volatile unsigned long long __force *) addr;
+}
+
+static inline void __raw_writeb(unsigned char b, volatile void __iomem *addr)
+{
+	*(volatile unsigned char __force *) addr = b;
+}
+static inline void __raw_writew(unsigned short b, volatile void __iomem *addr)
+{
+	*(volatile unsigned short __force *) addr = b;
+}
+static inline void __raw_writel(unsigned int b, volatile void __iomem *addr)
+{
+	*(volatile unsigned int __force *) addr = b;
+}
+static inline void __raw_writeq(unsigned long long b, volatile void __iomem *addr)
+{
+	*(volatile unsigned long long __force *) addr = b;
+}
 #else /* !USE_HPPA_IOREMAP */
+#define __raw_readb(addr) gsc_readb(addr)
+#define __raw_readw(addr) gsc_readw(addr)
+#define __raw_readl(addr) gsc_readl(addr)
+#define __raw_readq(addr) gsc_readq(addr)
+#define __raw_writeb(b, addr) gsc_writeb(b, addr)
+#define __raw_writew(b, addr) gsc_writew(b, addr)
+#define __raw_writel(b, addr) gsc_writel(b, addr)
+#define __raw_writeq(b, addr) gsc_writeq(b, addr)
+#endif /* !USE_HPPA_IOREMAP */
+
 #define readb(addr) __raw_readb(addr)
 #define readw(addr) le16_to_cpu(__raw_readw(addr))
 #define readl(addr) le32_to_cpu(__raw_readl(addr))
 #define readq(addr) le64_to_cpu(__raw_readq(addr))
-#define writeb(b,addr) __raw_writeb(b,addr)
-#define writew(b,addr) __raw_writew(cpu_to_le16(b),addr)
-#define writel(b,addr) __raw_writel(cpu_to_le32(b),addr)
-#define writeq(b,addr) __raw_writeq(cpu_to_le64(b),addr)
-#endif /* !USE_HPPA_IOREMAP */
+#define writeb(b, addr) __raw_writeb(b, addr)
+#define writew(b, addr) __raw_writew(cpu_to_le16(b), addr)
+#define writel(b, addr) __raw_writel(cpu_to_le32(b), addr)
+#define writeq(b, addr) __raw_writeq(cpu_to_le64(b), addr)
 
 #define readb_relaxed(addr) readb(addr)
 #define readw_relaxed(addr) readw(addr)
 #define readl_relaxed(addr) readl(addr)
 #define readq_relaxed(addr) readq(addr)
 
-#define mmiowb()
+#define mmiowb() do { } while (0)
 
-extern void __memcpy_fromio(unsigned long dest, unsigned long src, int count);
-extern void __memcpy_toio(unsigned long dest, unsigned long src, int count);
-extern void __memset_io(unsigned long dest, char fill, int count);
-
-#define memcpy_fromio(a,b,c) __memcpy_fromio((unsigned long)(a), (unsigned long)(b), (c))
-#define memcpy_toio(a,b,c)   __memcpy_toio((unsigned long)(a), (unsigned long)(b), (c))
-#define memset_io(a,b,c)     __memset_io((unsigned long)(a), (b), (c))
+void memset_io(volatile void __iomem *addr, unsigned char val, int count);
+void memcpy_fromio(void *dst, volatile void __iomem *src, int count);
+void memcpy_toio(volatile void __iomem *dst, const void *src, int count);
 
 /* Support old drivers which don't ioremap.
  * NB this interface is scheduled to disappear in 2.5
@@ -202,17 +226,6 @@ extern void __memset_io(unsigned long de
 #define isa_memcpy_fromio(a,b,c) memcpy_fromio((a), EISA_BASE | (b), (c))
 #define isa_memcpy_toio(a,b,c) memcpy_toio(EISA_BASE | (a), (b), (c))
 
-/* 
- * These functions support PA-RISC drivers which don't yet call ioremap().
- * They will disappear once the last of these drivers is gone.
- */
-#define gsc_readb(x) __raw_readb(x)
-#define gsc_readw(x) __raw_readw(x)
-#define gsc_readl(x) __raw_readl(x)
-#define gsc_writeb(x, y) __raw_writeb(x, y)
-#define gsc_writew(x, y) __raw_writew(x, y)
-#define gsc_writel(x, y) __raw_writel(x, y)
-
 
 /*
  * XXX - We don't have csum_partial_copy_fromio() yet, so we cheat here and 
@@ -305,5 +318,7 @@ extern void outsl (unsigned long port, c
  * bit I/O address (still with the leading f) and outputs the correct
  * value for either 32 or 64 bit mode */
 #define F_EXTEND(x) ((unsigned long)((x) | (0xffffffff00000000ULL)))
+
+#include <asm-generic/iomap.h>
 
 #endif
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-parisc/parisc-device.h parisc-2.6-bk/include/asm-parisc/parisc-device.h
--- linux-2.6.10-rc1-bk13/include/asm-parisc/parisc-device.h	Fri Oct 22 15:38:54 2004
+++ parisc-2.6-bk/include/asm-parisc/parisc-device.h	Wed Nov  3 06:19:18 2004
@@ -3,11 +3,7 @@
 struct parisc_device {
 	unsigned long   hpa;		/* Hard Physical Address */
 	struct parisc_device_id id;
-	struct parisc_device *parent;
-	struct parisc_device *sibling;
-	struct parisc_device *child;
 	struct parisc_driver *driver;	/* Driver for this device */
-	void		*sysdata;	/* Driver instance private data */
 	char		name[80];	/* The hardware description */
 	int		irq;
 
@@ -40,5 +36,6 @@ struct parisc_driver {
 
 #define to_parisc_device(d)	container_of(d, struct parisc_device, dev)
 #define to_parisc_driver(d)	container_of(d, struct parisc_driver, drv)
+#define parisc_parent(d)	to_parisc_device(d->dev.parent)
 
 extern struct bus_type parisc_bus_type;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-parisc/pdc.h parisc-2.6-bk/include/asm-parisc/pdc.h
--- linux-2.6.10-rc1-bk13/include/asm-parisc/pdc.h	Wed Nov  3 05:57:50 2004
+++ parisc-2.6-bk/include/asm-parisc/pdc.h	Wed Nov  3 06:19:19 2004
@@ -471,6 +471,13 @@ struct pdc_system_map_addr_info { /* PDC
 	unsigned long mod_pgs;
 };
 
+struct pdc_initiator { /* PDC_INITIATOR */
+	int host_id;
+	int factor;
+	int width;
+	int mode;
+};
+
 struct hardware_path {
 	char  flags;	/* see bit definitions below */
 	char  bc[6];	/* Bus Converter routing info to a specific */
@@ -732,10 +739,16 @@ int pdc_mem_map_hpa(struct pdc_memory_ma
 #endif /* !CONFIG_PA20 */
 int pdc_lan_station_id(char *lan_addr, unsigned long net_hpa);
 
+int pdc_stable_read(unsigned long staddr, void *memaddr, unsigned long count);
+int pdc_stable_write(unsigned long staddr, void *memaddr, unsigned long count);
+int pdc_stable_get_size(unsigned long *size);
+int pdc_stable_verify_contents(void);
+int pdc_stable_initialize(void);
+
 int pdc_pci_irt_size(unsigned long *num_entries, unsigned long hpa);
 int pdc_pci_irt(unsigned long num_entries, unsigned long hpa, void *tbl);
 
-int pdc_get_initiator(struct hardware_path *hwpath, unsigned char *scsi_id, unsigned long *period, char *width, char *mode);
+int pdc_get_initiator(struct hardware_path *, struct pdc_initiator *);
 int pdc_tod_read(struct pdc_tod *tod);
 int pdc_tod_set(unsigned long sec, unsigned long usec);
 
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-s390/compat.h parisc-2.6-bk/include/asm-s390/compat.h
--- linux-2.6.10-rc1-bk13/include/asm-s390/compat.h	Fri Oct 22 15:38:39 2004
+++ parisc-2.6-bk/include/asm-s390/compat.h	Wed Nov  3 06:19:19 2004
@@ -15,6 +15,9 @@ typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
 typedef u16		compat_uid_t;
 typedef u16		compat_gid_t;
+/* Define for use in compat_siginfo_t */
+#undef __ARCH_SI_COMPAT_UID_T
+#define __ARCH_SI_COMPAT_UID_T compat_uid32_t
 typedef u32		compat_uid32_t;
 typedef u32		compat_gid32_t;
 typedef u16		compat_mode_t;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/asm-sparc64/compat.h parisc-2.6-bk/include/asm-sparc64/compat.h
--- linux-2.6.10-rc1-bk13/include/asm-sparc64/compat.h	Fri Oct 22 15:39:43 2004
+++ parisc-2.6-bk/include/asm-sparc64/compat.h	Wed Nov  3 06:19:21 2004
@@ -12,6 +12,9 @@ typedef s32		compat_ssize_t;
 typedef s32		compat_time_t;
 typedef s32		compat_clock_t;
 typedef s32		compat_pid_t;
+/* Define for use in the compat_siginfo_t */
+#undef __ARCH_SI_COMPAT_UID_T
+#define __ARCH_SI_COMPAT_UID_T compat_uint_t
 typedef u16		compat_uid_t;
 typedef u16		compat_gid_t;
 typedef u16		compat_mode_t;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/compat.h parisc-2.6-bk/include/linux/compat.h
--- linux-2.6.10-rc1-bk13/include/linux/compat.h	Wed Nov  3 05:57:50 2004
+++ parisc-2.6-bk/include/linux/compat.h	Wed Nov  3 06:19:22 2004
@@ -6,10 +6,16 @@
  */
 #include <linux/config.h>
 
-#ifdef CONFIG_COMPAT
+#ifndef CONFIG_COMPAT
+
+/* Non-native task requiring compat... doesn't exist */
+#define is_compat_task(x) 0
+
+#else
 
 #include <linux/stat.h>
 #include <linux/param.h>	/* for HZ */
+#include <linux/personality.h>  /* Conditional process compat */
 #include <linux/sem.h>
 
 #include <asm/compat.h>
@@ -18,6 +24,11 @@
 #define compat_jiffies_to_clock_t(x)	\
 		(((unsigned long)(x) * COMPAT_USER_HZ) / HZ)
 
+/* Non-native task requiring compat */
+#ifndef HAVE_ARCH_IS_COMPAT_TASK
+#define is_compat_task(x) (personality(x->personality) == PER_LINUX32)
+#endif
+	
 struct compat_itimerspec { 
 	struct compat_timespec it_interval;
 	struct compat_timespec it_value;
@@ -87,27 +98,6 @@ struct compat_dirent {
 	u16		d_reclen;
 	char		d_name[256];
 };
-
-typedef union compat_sigval {
-	compat_int_t	sival_int;
-	compat_uptr_t	sival_ptr;
-} compat_sigval_t;
-
-typedef struct compat_sigevent {
-	compat_sigval_t sigev_value;
-	compat_int_t sigev_signo;
-	compat_int_t sigev_notify;
-	union {
-		compat_int_t _pad[SIGEV_PAD_SIZE];
-		compat_int_t _tid;
-
-		struct {
-			compat_uptr_t _function;
-			compat_uptr_t _attribute;
-		} _sigev_thread;
-	} _sigev_un;
-} compat_sigevent_t;
-
 
 long compat_sys_semctl(int first, int second, int third, void __user *uptr);
 long compat_sys_msgsnd(int first, int second, int third, void __user *uptr);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/compat_siginfo.h parisc-2.6-bk/include/linux/compat_siginfo.h
--- linux-2.6.10-rc1-bk13/include/linux/compat_siginfo.h	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/include/linux/compat_siginfo.h	Wed Nov  3 06:12:53 2004
@@ -0,0 +1,184 @@
+#ifndef _ASM_GENERIC_COMPAT_SIGINFO_H
+#define _ASM_GENERIC_COMPAT_SIGINFO_H
+
+#include <linux/config.h>
+#include <linux/compat.h>
+
+#ifndef CONFIG_COMPAT
+
+/* No compatibility layer required, add empty definitions for the compiler */
+
+typedef struct compat_siginfo{
+} compat_siginfo_t;
+
+static inline int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, 
+						struct siginfo *from)
+{
+	return -1;
+}
+
+static inline int compat_copy_siginfo_from_user(struct siginfo *to,
+                                                compat_siginfo_t __user *from)
+{
+        return -1;
+}
+
+#else
+
+#include <linux/compiler.h>
+#include <asm/siginfo.h>
+
+/* compat view of sigval_t */
+typedef union compat_sigval {
+	compat_int_t sival_int;
+	compat_uptr_t sival_ptr;
+} compat_sigval_t;
+
+/*
+ * This is the size (including padding) of the part of the
+ * struct siginfo that is before the union.
+ */
+#ifndef __ARCH_SI_COMPAT_PREAMBLE_SIZE
+#define __ARCH_SI_COMPAT_PREAMBLE_SIZE	(3 * sizeof(compat_int_t))
+#endif
+
+#define SI_COMPAT_MAX_SIZE	128
+#ifndef SI_COMPAT_PAD_SIZE
+#define SI_COMPAT_PAD_SIZE \
+  ((SI_COMPAT_MAX_SIZE - __ARCH_SI_COMPAT_PREAMBLE_SIZE) / sizeof(compat_int_t))
+#endif
+
+/* 32-bit view of si.uid_t */
+#ifndef __ARCH_SI_COMPAT_UID_T
+#define __ARCH_SI_COMPAT_UID_T compat_uid_t
+#endif
+
+/* 32-bit view of si.band_t */
+#ifndef __ARCH_SI_COMPAT_BAND_T
+#define __ARCH_SI_COMPAT_BAND_T compat_int_t
+#endif
+
+#ifndef HAVE_ARCH_COMPAT_SIGINFO_T
+
+/* Compat view of siginfo_t */
+typedef struct compat_siginfo {
+	compat_int_t si_signo;
+	compat_int_t si_errno;
+	compat_int_t si_code;
+
+	union {
+		compat_int_t _pad[SI_COMPAT_PAD_SIZE];
+
+		/* kill() */
+		struct {
+			compat_pid_t _pid;	/* sender's pid */
+			__ARCH_SI_COMPAT_UID_T _uid;	/* sender's uid */
+		} _kill;
+
+		/* POSIX.1b timers */
+		struct {
+			compat_timer_t _tid;	/* timer id */
+			compat_int_t _overrun;		/* overrun count */
+			char _pad[sizeof(__ARCH_SI_COMPAT_UID_T) - sizeof(compat_int_t)];
+			compat_sigval_t _sigval;	/* same as below */
+			compat_int_t _sys_private;       /* not to be passed to user */
+		} _timer;
+
+		/* POSIX.1b signals */
+		struct {
+			compat_pid_t _pid;		/* sender's pid */
+			__ARCH_SI_COMPAT_UID_T _uid;	/* sender's uid */
+			compat_sigval_t _sigval;
+		} _rt;
+
+		/* SIGCHLD */
+		struct {
+			compat_pid_t _pid;		/* which child */
+			__ARCH_SI_COMPAT_UID_T _uid;	/* sender's uid */
+			compat_int_t _status;		/* exit code */
+			compat_clock_t _utime;
+			compat_clock_t _stime;
+		} _sigchld;
+
+		/* SIGILL, SIGFPE, SIGSEGV, SIGBUS */
+		struct {
+			compat_uptr_t _addr; /* faulting insn/memory ref. */
+#ifdef __ARCH_SI_COMPAT_TRAPNO
+			compat_int_t _trapno;	/* TRAP # which caused the signal */
+#endif
+		} _sigfault;
+
+		/* SIGPOLL */
+		struct {
+			__ARCH_SI_COMPAT_BAND_T _band;	/* POLL_IN, POLL_OUT, POLL_MSG */
+			compat_int_t _fd;
+		} _sigpoll;
+	} _sifields;
+} compat_siginfo_t;
+#endif /* !HAVE_ARCH_COMPAT_SIGINFO_T */
+
+#ifdef __ARCH_SI_COMPAT_TRAPNO
+#define si_trapno	_sifields._sigfault._trapno
+#endif
+
+/*
+ * sigevent definitions
+ * 
+ * It seems likely that SIGEV_THREAD will have to be handled from 
+ * userspace, libpthread transmuting it to SIGEV_SIGNAL, which the
+ * thread manager then catches and does the appropriate nonsense.
+ * However, everything is written out here so as to not get lost.
+ */
+
+#ifndef __ARCH_SIGEV_COMPAT_PREAMBLE_SIZE
+#define __ARCH_SIGEV_COMPAT_PREAMBLE_SIZE (sizeof(compat_int_t) * 2 + sizeof(compat_sigval_t))
+#endif
+
+#define SIGEV_COMPAT_MAX_SIZE	64
+#ifndef SIGEV_COMPAT_PAD_SIZE
+#define SIGEV_COMPAT_PAD_SIZE	((SIGEV_COMPAT_MAX_SIZE - __ARCH_SIGEV_COMPAT_PREAMBLE_SIZE)/sizeof(compat_int_t))
+#endif
+
+#ifndef HAVE_ARCH_COMPAT_SIGEVENT_T
+
+/* 32-bit view of sigevent_t */
+typedef struct compat_sigevent {
+	compat_sigval_t sigev_value;
+	compat_int_t sigev_signo;
+	compat_int_t sigev_notify;
+	union {
+		compat_int_t _pad[SIGEV_COMPAT_PAD_SIZE];
+		compat_int_t _tid;
+
+		struct {
+			compat_uptr_t _function;
+			compat_uptr_t _attribute;	/* really pthread_attr_t */
+		} _sigev_thread;
+	} _sigev_un;
+} compat_sigevent_t;
+
+#endif /* HAVE_ARCH_COMPAT_SIGEVENT_T */
+
+#ifndef HAVE_ARCH_COMPAT_COPY_SIGINFO
+
+#include <linux/string.h>
+
+static inline void compat_copy_siginfo(struct compat_siginfo *to, struct compat_siginfo *from)
+{
+	if (from->si_code < 0)
+		memcpy(to, from, sizeof(*to));
+	else
+		/* _sigchld is currently the largest know union member */
+		memcpy(to, from, __ARCH_SI_COMPAT_PREAMBLE_SIZE + sizeof(from->_sifields._sigchld));
+}
+
+#endif /* !HAVE_ARCH_COMPAT_COPY_SIGINFO */
+
+extern int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, struct siginfo *from);
+extern int compat_copy_siginfo_from_user(struct siginfo *to, compat_siginfo_t __user *from);
+
+extern int compat_copy_sigevent_from_user(struct sigevent *to, compat_sigevent_t __user *from);
+
+#endif /* CONFIG_COMPAT */
+#endif /* _ASM_GENERIC_COMPAT_SIGINFO_H */
+
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/console.h parisc-2.6-bk/include/linux/console.h
--- linux-2.6.10-rc1-bk13/include/linux/console.h	Fri Oct 22 15:39:07 2004
+++ parisc-2.6-bk/include/linux/console.h	Wed Nov  3 06:19:22 2004
@@ -84,6 +84,7 @@ void give_up_console(const struct consw 
 #define CON_PRINTBUFFER	(1)
 #define CON_CONSDEV	(2) /* Last on the command line */
 #define CON_ENABLED	(4)
+#define CON_BOOT	(8)
 
 struct console
 {
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/hil.h parisc-2.6-bk/include/linux/hil.h
--- linux-2.6.10-rc1-bk13/include/linux/hil.h	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/include/linux/hil.h	Wed Nov  3 06:12:53 2004
@@ -0,0 +1,483 @@
+#ifndef _HIL_H_
+#define _HIL_H_
+
+/*
+ * Hewlett Packard Human Interface Loop (HP-HIL) Protocol -- header.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ * A note of thanks to HP for providing and shipping reference materials
+ * free of charge to help in the development of HIL support for Linux.
+ *
+ */
+
+#include <asm/types.h>
+
+/* Physical constants relevant to raw loop/device timing. 
+ */ 
+
+#define HIL_CLOCK		8MHZ
+#define HIL_EK1_CLOCK		30HZ
+#define HIL_EK2_CLOCK		60HZ
+
+#define HIL_TIMEOUT_DEV         5	/* ms */
+#define HIL_TIMEOUT_DEVS	10	/* ms */
+#define HIL_TIMEOUT_NORESP	10	/* ms */
+#define HIL_TIMEOUT_DEVS_DATA	16	/* ms */
+#define HIL_TIMEOUT_SELFTEST	200	/* ms */
+
+
+/* Actual wire line coding.  These will only be useful if someone is 
+ * implementing a software MLC to run HIL devices on a non-parisc machine.
+ */
+
+#define HIL_WIRE_PACKET_LEN	15
+enum hil_wire_bitpos {
+	HIL_WIRE_START		= 0,
+	HIL_WIRE_ADDR2,
+	HIL_WIRE_ADDR1,
+	HIL_WIRE_ADDR0,
+	HIL_WIRE_COMMAND,
+	HIL_WIRE_DATA7,
+	HIL_WIRE_DATA6,
+	HIL_WIRE_DATA5,
+	HIL_WIRE_DATA4,
+	HIL_WIRE_DATA3,
+	HIL_WIRE_DATA2,
+	HIL_WIRE_DATA1,
+	HIL_WIRE_DATA0,
+	HIL_WIRE_PARITY,
+	HIL_WIRE_STOP
+};
+
+/* HP documentation uses these bit positions to refer to commands;
+ * we will call these "packets".
+ */
+enum hil_pkt_bitpos {
+	HIL_PKT_CMD		= 0x00000800,
+	HIL_PKT_ADDR2		= 0x00000400,
+	HIL_PKT_ADDR1		= 0x00000200,
+	HIL_PKT_ADDR0		= 0x00000100,
+	HIL_PKT_ADDR_MASK	= 0x00000700,
+	HIL_PKT_ADDR_SHIFT	= 8,
+	HIL_PKT_DATA7		= 0x00000080,
+	HIL_PKT_DATA6		= 0x00000040,
+	HIL_PKT_DATA5		= 0x00000020,
+	HIL_PKT_DATA4		= 0x00000010,
+	HIL_PKT_DATA3		= 0x00000008,
+	HIL_PKT_DATA2		= 0x00000004,
+	HIL_PKT_DATA1		= 0x00000002,
+	HIL_PKT_DATA0		= 0x00000001,
+	HIL_PKT_DATA_MASK	= 0x000000FF,
+	HIL_PKT_DATA_SHIFT	= 0
+};
+
+/* The HIL MLC also has several error/status/control bits.  We extend the 
+ * "packet" to include these when direct access to the MLC is available,
+ * or emulate them in cases where they are not available. 
+ *
+ * This way the device driver knows that the underlying MLC driver
+ * has had to deal with loop errors.
+ */
+enum hil_error_bitpos {
+	HIL_ERR_OB	= 0x00000800, /* MLC is busy sending an auto-poll, 
+					 or we have filled up the output 
+					 buffer and must wait. */
+	HIL_ERR_INT	= 0x00010000, /* A normal interrupt has occurred. */
+	HIL_ERR_NMI	= 0x00020000, /* An NMI has occurred. */
+	HIL_ERR_LERR	= 0x00040000, /* A poll didn't come back. */
+	HIL_ERR_PERR	= 0x01000000, /* There was a Parity Error. */
+	HIL_ERR_FERR	= 0x02000000, /* There was a Framing Error. */
+	HIL_ERR_FOF	= 0x04000000  /* Input FIFO Overflowed. */
+};
+
+enum hil_control_bitpos {
+	HIL_CTRL_TEST	= 0x00010000,
+	HIL_CTRL_IPF	= 0x00040000,
+	HIL_CTRL_APE	= 0x02000000
+};
+
+/* Bits 30,31 are unused, we use them to control write behavior. */
+#define HIL_DO_ALTER_CTRL  0x40000000 /* Write MSW of packet to control 
+                                          before writing LSW to loop */
+#define HIL_CTRL_ONLY      0xc0000000 /* *Only* alter the control registers */
+
+/* This gives us a 32-bit "packet" 
+ */
+typedef u32 hil_packet;
+
+
+/* HIL Loop commands 
+ */
+enum hil_command {
+	HIL_CMD_IFC	= 0x00,	/* Interface Clear */
+	HIL_CMD_EPT	= 0x01,	/* Enter Pass-Thru Mode */
+	HIL_CMD_ELB	= 0x02,	/* Enter Loop-Back Mode */
+	HIL_CMD_IDD	= 0x03,	/* Identify and Describe */
+	HIL_CMD_DSR	= 0x04,	/* Device Soft Reset */
+	HIL_CMD_PST	= 0x05,	/* Perform Self Test */
+	HIL_CMD_RRG	= 0x06,	/* Read Register */
+	HIL_CMD_WRG	= 0x07,	/* Write Register */
+	HIL_CMD_ACF	= 0x08,	/* Auto Configure */
+	HIL_CMDID_ACF	= 0x07,	/* Auto Configure bits with incremented ID */
+	HIL_CMD_POL	= 0x10,	/* Poll */
+	HIL_CMDCT_POL	= 0x0f,	/* Poll command bits with item count  */
+	HIL_CMD_RPL	= 0x20,	/* RePoll */
+	HIL_CMDCT_RPL	= 0x0f,	/* RePoll command bits with item count */
+	HIL_CMD_RNM	= 0x30,	/* Report Name */
+	HIL_CMD_RST	= 0x31,	/* Report Status */
+	HIL_CMD_EXD	= 0x32,	/* Extended Describe */
+	HIL_CMD_RSC	= 0x33,	/* Report Security Code */
+
+	/* 0x34 to 0x3c reserved for future use  */
+
+	HIL_CMD_DKA	= 0x3d,	/* Disable Keyswitch Autorepeat */
+	HIL_CMD_EK1	= 0x3e,	/* Enable Keyswitch Autorepeat 1 */
+	HIL_CMD_EK2	= 0x3f,	/* Enable Keyswitch Autorepeat 2 */
+	HIL_CMD_PR1	= 0x40,	/* Prompt1 */  
+	HIL_CMD_PR2	= 0x41,	/* Prompt2 */
+	HIL_CMD_PR3	= 0x42,	/* Prompt3 */
+	HIL_CMD_PR4	= 0x43,	/* Prompt4 */
+	HIL_CMD_PR5	= 0x44,	/* Prompt5 */
+	HIL_CMD_PR6	= 0x45,	/* Prompt6 */
+	HIL_CMD_PR7	= 0x46,	/* Prompt7 */
+	HIL_CMD_PRM	= 0x47,	/* Prompt (General Purpose) */
+	HIL_CMD_AK1	= 0x48,	/* Acknowlege1 */  
+	HIL_CMD_AK2	= 0x49,	/* Acknowlege2 */
+	HIL_CMD_AK3	= 0x4a,	/* Acknowlege3 */
+	HIL_CMD_AK4	= 0x4b,	/* Acknowlege4 */
+	HIL_CMD_AK5	= 0x4c,	/* Acknowlege5 */
+	HIL_CMD_AK6	= 0x4d,	/* Acknowlege6 */
+	HIL_CMD_AK7	= 0x4e,	/* Acknowlege7 */
+	HIL_CMD_ACK	= 0x4f,	/* Acknowlege (General Purpose) */
+
+	/* 0x50 to 0x78 reserved for future use  */
+	/* 0x80 to 0xEF device-specific commands */
+	/* 0xf0 to 0xf9 reserved for future use  */
+
+	HIL_CMD_RIO	= 0xfa,	/* Register I/O Error */
+	HIL_CMD_SHR	= 0xfb,	/* System Hard Reset */
+	HIL_CMD_TER	= 0xfc,	/* Transmission Error */
+	HIL_CMD_CAE	= 0xfd,	/* Configuration Address Error */
+	HIL_CMD_DHR	= 0xfe,	/* Device Hard Reset */
+
+	/* 0xff is prohibited from use. */
+};
+
+
+/* 
+ * Response "records" to HIL commands
+ */
+
+/* Device ID byte 
+ */
+#define HIL_IDD_DID_TYPE_MASK		0xe0	/* Primary type bits */
+#define HIL_IDD_DID_TYPE_KB_INTEGRAL	0xa0	/* Integral keyboard */
+#define HIL_IDD_DID_TYPE_KB_ITF		0xc0	/* ITD keyboard */
+#define HIL_IDD_DID_TYPE_KB_RSVD	0xe0	/* Reserved keyboard type */
+#define HIL_IDD_DID_TYPE_KB_LANG_MASK	0x1f	/* Keyboard locale bits */
+#define HIL_IDD_DID_KBLANG_USE_ESD	0x00	/* Use ESD Locale instead */
+#define HIL_IDD_DID_TYPE_ABS		0x80    /* Absolute Positioners */
+#define HIL_IDD_DID_ABS_RSVD1_MASK	0xf8	/* Reserved */
+#define HIL_IDD_DID_ABS_RSVD1		0x98
+#define HIL_IDD_DID_ABS_TABLET_MASK	0xf8	/* Tablets and digitizers */
+#define HIL_IDD_DID_ABS_TABLET		0x90
+#define HIL_IDD_DID_ABS_TSCREEN_MASK	0xfc	/* Touch screens */
+#define HIL_IDD_DID_ABS_TSCREEN		0x8c
+#define HIL_IDD_DID_ABS_RSVD2_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_ABS_RSVD2		0x88
+#define HIL_IDD_DID_ABS_RSVD3_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_ABS_RSVD3		0x80
+#define HIL_IDD_DID_TYPE_REL		0x60    /* Relative Positioners */
+#define HIL_IDD_DID_REL_RSVD1_MASK	0xf0	/* Reserved */
+#define HIL_IDD_DID_REL_RSVD1		0x70
+#define HIL_IDD_DID_REL_RSVD2_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_REL_RSVD2		0x6c
+#define HIL_IDD_DID_REL_MOUSE_MASK	0xfc	/* Mouse */
+#define HIL_IDD_DID_REL_MOUSE		0x68
+#define HIL_IDD_DID_REL_QUAD_MASK	0xf8	/* Other Quadrature Devices */
+#define HIL_IDD_DID_REL_QUAD		0x60
+#define HIL_IDD_DID_TYPE_CHAR		0x40    /* Character Entry */
+#define HIL_IDD_DID_CHAR_BARCODE_MASK	0xfc	/* Barcode Reader */
+#define HIL_IDD_DID_CHAR_BARCODE	0x5c
+#define HIL_IDD_DID_CHAR_RSVD1_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_CHAR_RSVD1		0x58
+#define HIL_IDD_DID_CHAR_RSVD2_MASK	0xf8	/* Reserved */
+#define HIL_IDD_DID_CHAR_RSVD2		0x50
+#define HIL_IDD_DID_CHAR_RSVD3_MASK	0xf0	/* Reserved */
+#define HIL_IDD_DID_CHAR_RSVD3		0x40
+#define HIL_IDD_DID_TYPE_OTHER		0x20    /* Miscellaneous */
+#define HIL_IDD_DID_OTHER_RSVD1_MASK	0xf0	/* Reserved */
+#define HIL_IDD_DID_OTHER_RSVD1		0x30
+#define HIL_IDD_DID_OTHER_BARCODE_MASK	0xfc	/* Tone Generator */
+#define HIL_IDD_DID_OTHER_BARCODE	0x2c
+#define HIL_IDD_DID_OTHER_RSVD2_MASK	0xfc	/* Reserved */
+#define HIL_IDD_DID_OTHER_RSVD2		0x28
+#define HIL_IDD_DID_OTHER_RSVD3_MASK	0xf8	/* Reserved */
+#define HIL_IDD_DID_OTHER_RSVD3		0x20
+#define HIL_IDD_DID_TYPE_KEYPAD		0x00	/* Vectra Keyboard */
+
+/* IDD record header 
+ */
+#define HIL_IDD_HEADER_AXSET_MASK	0x03    /* Number of axis in a set */
+#define HIL_IDD_HEADER_RSC		0x04	/* Supports RSC command */
+#define HIL_IDD_HEADER_EXD		0x08	/* Supports EXD command */
+#define HIL_IDD_HEADER_IOD		0x10	/* IOD byte to follow */
+#define HIL_IDD_HEADER_16BIT		0x20	/* 16 (vs. 8) bit resolution */
+#define HIL_IDD_HEADER_ABS		0x40	/* Reports Absolute Position */
+#define HIL_IDD_HEADER_2X_AXIS		0x80	/* Two sets of 1-3 axis */
+
+/* I/O Descriptor
+ */
+#define HIL_IDD_IOD_NBUTTON_MASK	0x07	/* Number of buttons */
+#define HIL_IDD_IOD_PROXIMITY		0x08	/* Proximity in/out events */
+#define HIL_IDD_IOD_PROMPT_MASK		0x70	/* Number of prompts/acks */
+#define HIL_IDD_IOD_PROMPT_SHIFT	4
+#define HIL_IDD_IOD_PROMPT		0x80	/* Generic prompt/ack */
+
+#define HIL_IDD_NUM_AXES_PER_SET(header_packet) \
+((header_packet) & HIL_IDD_HEADER_AXSET_MASK)
+
+#define HIL_IDD_NUM_AXSETS(header_packet) \
+(2 - !((header_packet) & HIL_IDD_HEADER_2X_AXIS))
+
+#define HIL_IDD_LEN(header_packet) \
+((4 - !(header_packet & HIL_IDD_HEADER_IOD) -			\
+  2 * !(HIL_IDD_NUM_AXES_PER_SET(header_packet))) +		\
+  2 * HIL_IDD_NUM_AXES_PER_SET(header_packet) *			\
+ !!((header_packet) & HIL_IDD_HEADER_ABS))
+
+/* The following HIL_IDD_* macros assume you have an array of 
+ * packets and/or unpacked 8-bit data in the order that they 
+ * were received.
+ */
+
+#define HIL_IDD_AXIS_COUNTS_PER_M(header_ptr) \
+(!(HIL_IDD_NUM_AXSETS(*(header_ptr))) ? -1 :			\
+(((*(header_ptr + 1) & HIL_PKT_DATA_MASK) +			\
+  ((*(header_ptr + 2) & HIL_PKT_DATA_MASK)) << 8)		\
+* ((*(header_ptr) & HIL_IDD_HEADER_16BIT) ? 100 : 1)))
+
+#define HIL_IDD_AXIS_MAX(header_ptr, __axnum) \
+((!(*(header_ptr) & HIL_IDD_HEADER_ABS) ||			\
+  (HIL_IDD_NUM_AXES_PER_SET(*(header_ptr)) <= __axnum)) ? 0 :	\
+ ((HIL_PKT_DATA_MASK & *((header_ptr) + 3 + 2 * __axnum)) +	\
+  ((HIL_PKT_DATA_MASK & *((header_ptr) + 4 + 2 * __axnum)) << 8)))
+
+#define HIL_IDD_IOD(header_ptr) \
+(*(header_ptr + HIL_IDD_LEN((*header_ptr)) - 1))
+
+#define HIL_IDD_HAS_GEN_PROMPT(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) &&				\
+ (HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_PROMPT))
+
+#define HIL_IDD_HAS_GEN_PROXIMITY(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) &&				\
+ (HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_PROXIMITY))
+
+#define HIL_IDD_NUM_BUTTONS(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) ?				\
+ (HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_NBUTTON_MASK) : 0)
+
+#define HIL_IDD_NUM_PROMPTS(header_ptr) \
+((*header_ptr & HIL_IDD_HEADER_IOD) ?				\
+ ((HIL_IDD_IOD(header_ptr) & HIL_IDD_IOD_NPROMPT_MASK)		\
+  >> HIL_IDD_IOD_PROMPT_SHIFT) : 0)
+
+/* The response to HIL EXD commands -- the "extended describe record" */
+#define	HIL_EXD_HEADER_WRG		0x03	/* Supports type2 WRG */
+#define HIL_EXD_HEADER_WRG_TYPE1	0x01	/* Supports type1 WRG */
+#define	HIL_EXD_HEADER_WRG_TYPE2	0x02	/* Supports type2 WRG */
+#define	HIL_EXD_HEADER_RRG		0x04	/* Supports RRG command */
+#define	HIL_EXD_HEADER_RNM		0x10	/* Supports RNM command */
+#define HIL_EXD_HEADER_RST		0x20	/* Supports RST command */
+#define HIL_EXD_HEADER_LOCALE		0x40	/* Contains locale code */
+
+#define HIL_EXD_NUM_RRG(header_ptr) \
+((*header_ptr & HIL_EXD_HEADER_RRG) ? \
+ (*(header_ptr + 1) & HIL_PKT_DATA_MASK) : 0)
+
+#define HIL_EXD_NUM_WWG(header_ptr) \
+((*header_ptr & HIL_EXD_HEADER_WRG) ?				\
+ (*(header_ptr + 2 - !(*header_ptr & HIL_EXD_HEADER_RRG)) &	\
+    HIL_PKT_DATA_MASK) : 0)
+
+#define HIL_EXD_LEN(header_ptr) \
+(!!(*header_ptr & HIL_EXD_HEADER_RRG) +				\
+ !!(*header_ptr & HIL_EXD_HEADER_WRG) +				\
+ !!(*header_ptr & HIL_EXD_HEADER_LOCALE) +			\
+ 2 * !!(*header_ptr & HIL_EXD_HEADER_WRG_TYPE2) + 1)
+
+#define HIL_EXD_LOCALE(header_ptr) \
+(!(*header_ptr & HIL_EXD_HEADER_LOCALE) ? -1 :			\
+ (*(header_ptr + HIL_EXD_LEN(header_ptr) - 1) & HIL_PKT_DATA_MASK))
+
+#define HIL_EXD_WRG_TYPE2_LEN(header_ptr) \
+(!(*header_ptr & HIL_EXD_HEADER_WRG_TYPE2) ? -1	:			\
+ (*(header_ptr + HIL_EXD_LEN(header_ptr) - 2 -                  	\
+    !!(*header_ptr & HIL_EXD_HEADER_LOCALE)) & HIL_PKT_DATA_MASK) +	\
+ ((*(header_ptr + HIL_EXD_LEN(header_ptr) - 1 -				\
+     !!(*header_ptr & HIL_EXD_HEADER_LOCALE)) & HIL_PKT_DATA_MASK) << 8))
+
+/* Device locale codes. */ 
+
+/* Last defined locale code.  Everything above this is "Reserved",
+   and note that this same table applies to the Device ID Byte where 
+   keyboards may have a nationality code which is only 5 bits. */
+#define HIL_LOCALE_MAX 0x1f
+
+/* Map to hopefully useful strings.  I was trying to make these look
+   like locale.aliases strings do; maybe that isn't the right table to
+   emulate.  In either case, I didn't have much to work on. */
+#define HIL_LOCALE_MAP \
+"",			/* 0x00 Reserved */		\
+"",			/* 0x01 Reserved */		\
+"",			/* 0x02 Reserved */		\
+"swiss.french",		/* 0x03 Swiss/French */		\
+"portuguese",		/* 0x04 Portuguese */		\
+"arabic",		/* 0x05 Arabic */		\
+"hebrew",		/* 0x06 Hebrew */		\
+"english.canadian",	/* 0x07 Canadian English */	\
+"turkish",		/* 0x08 Turkish */		\
+"greek",		/* 0x09 Greek */		\
+"thai",			/* 0x0a Thai (Thailand) */	\
+"italian",		/* 0x0b Italian */		\
+"korean",		/* 0x0c Hangul (Korea) */	\
+"dutch",		/* 0x0d Dutch */		\
+"swedish",		/* 0x0e Swedish */		\
+"german",		/* 0x0f German */		\
+"chinese",		/* 0x10 Chinese-PRC */		\
+"chinese",		/* 0x11 Chinese-ROC */		\
+"swiss.french",		/* 0x12 Swiss/French II */	\
+"spanish",		/* 0x13 Spanish */		\
+"swiss.german",		/* 0x14 Swiss/German II */	\
+"flemish",		/* 0x15 Belgian (Flemish) */	\
+"finnish",		/* 0x16 Finnish	*/		\
+"english.uk",		/* 0x17 United Kingdom */	\
+"french.canadian",	/* 0x18 French/Canadian */	\
+"swiss.german",		/* 0x19 Swiss/German */		\
+"norwegian",		/* 0x1a Norwegian */		\
+"french",		/* 0x1b French */		\
+"danish",		/* 0x1c Danish */		\
+"japanese",		/* 0x1d Katakana */		\
+"spanish",		/* 0x1e Latin American/Spanish*/\
+"english.us"		/* 0x1f United States */	\
+
+
+/* HIL keycodes */
+#define HIL_KEYCODES_SET1_TBLSIZE 128
+#define HIL_KEYCODES_SET1 	\
+   KEY_5,		KEY_RESERVED,	KEY_RIGHTALT,	KEY_LEFTALT,	\
+   KEY_RIGHTSHIFT,	KEY_LEFTSHIFT,	KEY_LEFTCTRL,	KEY_SYSRQ,	\
+   KEY_KP4,		KEY_KP8,	KEY_KP5,	KEY_KP9,	\
+   KEY_KP6,		KEY_KP7,	KEY_KPCOMMA,	KEY_KPENTER,	\
+   KEY_KP1,		KEY_KPSLASH,	KEY_KP2,	KEY_KPPLUS,	\
+   KEY_KP3,		KEY_KPASTERISK,	KEY_KP0,	KEY_KPMINUS,	\
+   KEY_B,		KEY_V,		KEY_C,		KEY_X,		\
+   KEY_Z,		KEY_RESERVED,	KEY_RESERVED,   KEY_ESC,	\
+   KEY_6,		KEY_F10,	KEY_3,		KEY_F11,	\
+   KEY_KPDOT,		KEY_F9,		KEY_TAB /*KP*/,	KEY_F12,	\
+   KEY_H,		KEY_G,		KEY_F,		KEY_D,		\
+   KEY_S,		KEY_A,		KEY_RESERVED,	KEY_CAPSLOCK,	\
+   KEY_U,		KEY_Y,		KEY_T,		KEY_R,		\
+   KEY_E,		KEY_W,		KEY_Q,		KEY_TAB,	\
+   KEY_7,		KEY_6,		KEY_5,		KEY_4,		\
+   KEY_3,		KEY_2,		KEY_1,		KEY_GRAVE,	\
+   KEY_F13,		KEY_F14,	KEY_F15,	KEY_F16,	\
+   KEY_F17,		KEY_F18,	KEY_F19,	KEY_F20,	\
+   KEY_MENU,		KEY_F4,		KEY_F3,		KEY_F2,		\
+   KEY_F1,		KEY_VOLUMEUP,	KEY_STOP,	KEY_SENDFILE,	\
+   KEY_SYSRQ,		KEY_F5,		KEY_F6,		KEY_F7,		\
+   KEY_F8,		KEY_VOLUMEDOWN,	KEY_DEL_EOL,	KEY_DEL_EOS,	\
+   KEY_8,		KEY_9,		KEY_0,		KEY_MINUS,	\
+   KEY_EQUAL,		KEY_BACKSPACE,	KEY_INS_LINE,	KEY_DEL_LINE,	\
+   KEY_I,		KEY_O,		KEY_P,		KEY_LEFTBRACE,	\
+   KEY_RIGHTBRACE,	KEY_BACKSLASH,	KEY_INSERT,	KEY_DELETE,	\
+   KEY_J,		KEY_K,		KEY_L,		KEY_SEMICOLON,	\
+   KEY_APOSTROPHE,	KEY_ENTER,	KEY_HOME,	KEY_PAGEUP,	\
+   KEY_M,		KEY_COMMA,	KEY_DOT,	KEY_SLASH,	\
+   KEY_BACKSLASH,	KEY_SELECT,	KEY_102ND,	KEY_PAGEDOWN,	\
+   KEY_N,		KEY_SPACE,	KEY_NEXT,	KEY_RESERVED,	\
+   KEY_LEFT,		KEY_DOWN,	KEY_UP,		KEY_RIGHT
+
+
+#define HIL_KEYCODES_SET3_TBLSIZE 128
+#define HIL_KEYCODES_SET3 	\
+  KEY_RESERVED,	KEY_ESC,	KEY_1,		KEY_2,			\
+  KEY_3,	KEY_4,		KEY_5,		KEY_6,			\
+  KEY_7,	KEY_8,		KEY_9,		KEY_0,			\
+  KEY_MINUS,	KEY_EQUAL,	KEY_BACKSPACE,	KEY_TAB,		\
+  KEY_Q,	KEY_W,		KEY_E,		KEY_R,			\
+  KEY_T,	KEY_Y,		KEY_U,		KEY_I,			\
+  KEY_O,	KEY_P,		KEY_LEFTBRACE,	KEY_RIGHTBRACE,		\
+  KEY_ENTER,	KEY_LEFTCTRL,	KEY_A,		KEY_S,			\
+  KEY_D,	KEY_F,		KEY_G,		KEY_H,			\
+  KEY_J,	KEY_K,		KEY_L,		KEY_SEMICOLON,		\
+  KEY_APOSTROPHE,KEY_GRAVE,	KEY_LEFTSHIFT,	KEY_BACKSLASH,		\
+  KEY_Z,	KEY_X,		KEY_C,		KEY_V,			\
+  KEY_B,	KEY_N,		KEY_M,		KEY_COMMA,		\
+  KEY_DOT,	KEY_SLASH,	KEY_RIGHTSHIFT,	KEY_KPASTERISK,		\
+  KEY_LEFTALT,	KEY_SPACE,	KEY_CAPSLOCK,	KEY_F1,			\
+  KEY_F2,	KEY_F3,		KEY_F4,		KEY_F5,			\
+  KEY_F6,	KEY_F7,		KEY_F8,		KEY_F9,			\
+  KEY_F10,	KEY_NUMLOCK,	KEY_SCROLLLOCK,	KEY_KP7,		\
+  KEY_KP8,	KEY_KP9,	KEY_KPMINUS,	KEY_KP4,		\
+  KEY_KP5,	KEY_KP6,	KEY_KPPLUS,	KEY_KP1,		\
+  KEY_KP2,	KEY_KP3,	KEY_KP0,	KEY_KPDOT,		\
+  KEY_SYSRQ,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_UP,	KEY_LEFT,	KEY_DOWN,	KEY_RIGHT,		\
+  KEY_HOME,	KEY_PAGEUP,	KEY_END,	KEY_PAGEDOWN,		\
+  KEY_INSERT,	KEY_DELETE,	KEY_102ND,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_F1,	KEY_F2,		KEY_F3,		KEY_F4,			\
+  KEY_F5,	KEY_F6,		KEY_F7,		KEY_F8,			\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,		\
+  KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED,	KEY_RESERVED
+
+
+/* Response to POL command, the "poll record header" */
+
+#define HIL_POL_NUM_AXES_MASK	0x03	/* Number of axis reported */
+#define HIL_POL_CTS		0x04	/* Device ready to receive data */
+#define HIL_POL_STATUS_PENDING	0x08	/* Device has status to report */
+#define HIL_POL_CHARTYPE_MASK	0x70	/* Type of character data to follow */
+#define HIL_POL_CHARTYPE_NONE	0x00	/* No character data to follow */
+#define HIL_POL_CHARTYPE_RSVD1	0x10	/* Reserved Set 1 */
+#define HIL_POL_CHARTYPE_ASCII	0x20	/* U.S. ASCII */
+#define HIL_POL_CHARTYPE_BINARY	0x30	/* Binary data */
+#define HIL_POL_CHARTYPE_SET1	0x40	/* Keycode Set 1 */
+#define HIL_POL_CHARTYPE_RSVD2	0x50	/* Reserved Set 2 */
+#define HIL_POL_CHARTYPE_SET2	0x60	/* Keycode Set 2 */
+#define HIL_POL_CHARTYPE_SET3	0x70	/* Keycode Set 3 */
+#define HIL_POL_AXIS_ALT	0x80	/* Data is from axis set 2 */
+
+
+#endif /* _HIL_H_ */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/hil_mlc.h parisc-2.6-bk/include/linux/hil_mlc.h
--- linux-2.6.10-rc1-bk13/include/linux/hil_mlc.h	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/include/linux/hil_mlc.h	Wed Nov  3 06:12:53 2004
@@ -0,0 +1,168 @@
+/*
+ * HP Human Interface Loop Master Link Controller driver.
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ */
+
+#include <linux/hil.h>
+#include <linux/time.h>
+#include <linux/interrupt.h>
+#include <asm/semaphore.h>
+#include <linux/serio.h>
+#include <linux/list.h>
+
+typedef struct hil_mlc hil_mlc;
+
+/* The HIL has a complicated state engine.
+ * We define the structure of nodes in the state engine here.
+ */
+enum hilse_act {
+  	/* HILSE_OUT prepares to receive input if the next node
+	 * is an IN or EXPECT, and then sends the given packet.
+	 */
+	HILSE_OUT = 0,
+
+  	/* HILSE_CTS checks if the loop is busy. */
+	HILSE_CTS,
+
+	/* HILSE_OUT_LAST sends the given command packet to 
+	 * the last configured/running device on the loop.
+	 */
+	HILSE_OUT_LAST,
+
+	/* HILSE_OUT_DISC sends the given command packet to
+	 * the next device past the last configured/running one.
+	 */
+	HILSE_OUT_DISC,
+
+	/* HILSE_FUNC runs a callback function with given arguments.
+	 * a positive return value causes the "ugly" branch to be taken.
+	 */
+	HILSE_FUNC,
+
+  	/* HILSE_IN simply expects any non-errored packet to arrive 
+	 * within arg usecs.
+	 */
+	HILSE_IN		= 0x100,
+
+  	/* HILSE_EXPECT expects a particular packet to arrive 
+	 * within arg usecs, any other packet is considered an error.
+	 */
+	HILSE_EXPECT,
+
+  	/* HILSE_EXPECT_LAST as above but dev field should be last 
+	 * discovered/operational device.
+	 */
+	HILSE_EXPECT_LAST,
+
+  	/* HILSE_EXPECT_LAST as above but dev field should be first 
+	 * undiscovered/inoperational device.
+	 */
+	HILSE_EXPECT_DISC
+};
+
+typedef int	(hilse_func) (hil_mlc *mlc, int arg);
+struct hilse_node {
+	enum hilse_act		act;	/* How to process this node         */
+	union {
+		hilse_func	*func;	/* Function to call if HILSE_FUNC   */
+		hil_packet	packet;	/* Packet to send or to compare     */
+	} object;
+	int			arg;	/* Timeout in usec or parm for func */
+	int			good;	/* Node to jump to on success       */
+	int			bad;	/* Node to jump to on error         */
+	int			ugly;	/* Node to jump to on timeout       */
+};
+
+/* Methods for back-end drivers, e.g. hp_sdc_mlc */
+typedef int	(hil_mlc_cts) (hil_mlc *mlc);
+typedef void	(hil_mlc_out) (hil_mlc *mlc);
+typedef int	(hil_mlc_in)  (hil_mlc *mlc, suseconds_t timeout);
+
+struct hil_mlc_devinfo {
+	uint8_t	idd[16];	/* Device ID Byte and Describe Record */
+	uint8_t	rsc[16];	/* Security Code Header and Record */
+	uint8_t	exd[16];	/* Extended Describe Record */
+	uint8_t	rnm[16];	/* Device name as returned by RNM command */
+};
+
+struct hil_mlc_serio_map {
+	hil_mlc *mlc;
+	int di_revmap;
+	int didx;
+};
+
+/* How many (possibly old/detached) devices the we try to keep track of */
+#define HIL_MLC_DEVMEM 16
+
+struct hil_mlc {
+	struct list_head	list;	/* hil_mlc is organized as linked list */
+
+	rwlock_t		lock;
+
+	void *priv; /* Data specific to a particular type of MLC */
+
+	int 			seidx;	/* Current node in state engine */
+	int			istarted, ostarted;
+
+	hil_mlc_cts		*cts;
+	struct semaphore	csem;   /* Raised when loop idle */
+
+	hil_mlc_out		*out;
+	struct semaphore	osem;   /* Raised when outpacket dispatched */
+	hil_packet		opacket;
+
+	hil_mlc_in		*in;
+	struct semaphore	isem;   /* Raised when a packet arrives */
+	hil_packet		ipacket[16];
+	hil_packet		imatch;
+	int			icount;
+	struct timeval		instart;
+	suseconds_t		intimeout;
+
+	int			ddi;	/* Last operational device id */
+	int			lcv;	/* LCV to throttle loops */
+	struct timeval		lcv_tv; /* Time loop was started */
+
+	int			di_map[7]; /* Maps below items to live devs */
+	struct hil_mlc_devinfo	di[HIL_MLC_DEVMEM];
+	struct serio		*serio[HIL_MLC_DEVMEM];
+	struct hil_mlc_serio_map serio_map[HIL_MLC_DEVMEM];
+	hil_packet		serio_opacket[HIL_MLC_DEVMEM];
+	int			serio_oidx[HIL_MLC_DEVMEM];
+	struct hil_mlc_devinfo	di_scratch; /* Temporary area */
+
+	int			opercnt;
+
+	struct tasklet_struct	*tasklet;
+};
+
+int hil_mlc_register(hil_mlc *mlc);
+int hil_mlc_unregister(hil_mlc *mlc);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/hp_sdc.h parisc-2.6-bk/include/linux/hp_sdc.h
--- linux-2.6.10-rc1-bk13/include/linux/hp_sdc.h	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/include/linux/hp_sdc.h	Wed Nov  3 06:12:53 2004
@@ -0,0 +1,300 @@
+/*
+ * HP i8042 System Device Controller -- header
+ *
+ * Copyright (c) 2001 Brian S. Julin
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions, and the following disclaimer,
+ *    without modification.
+ * 2. The name of the author may not be used to endorse or promote products
+ *    derived from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL").
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ *
+ * References:
+ * 
+ * HP-HIL Technical Reference Manual.  Hewlett Packard Product No. 45918A
+ *
+ * System Device Controller Microprocessor Firmware Theory of Operation
+ * 	for Part Number 1820-4784 Revision B.  Dwg No. A-1820-4784-2
+ *
+ */
+
+#ifndef _LINUX_HP_SDC_H
+#define _LINUX_HP_SDC_H
+
+#include <linux/interrupt.h>
+#include <linux/types.h>
+#include <linux/time.h>
+#include <linux/timer.h>
+#if defined(__hppa__)
+#include <asm/hardware.h>
+#endif
+
+
+/* No 4X status reads take longer than this (in usec).
+ */
+#define HP_SDC_MAX_REG_DELAY 20000
+
+typedef void (hp_sdc_irqhook) (int irq, void *dev_id, 
+			       uint8_t status, uint8_t data);
+
+int hp_sdc_request_timer_irq(hp_sdc_irqhook *callback);
+int hp_sdc_request_hil_irq(hp_sdc_irqhook *callback);
+int hp_sdc_request_cooked_irq(hp_sdc_irqhook *callback);
+int hp_sdc_release_timer_irq(hp_sdc_irqhook *callback);
+int hp_sdc_release_hil_irq(hp_sdc_irqhook *callback);
+int hp_sdc_release_cooked_irq(hp_sdc_irqhook *callback);
+
+typedef struct {
+	int actidx;	/* Start of act.  Acts are atomic WRT I/O to SDC */
+	int idx;	/* Index within the act */
+	int endidx;	/* transaction is over and done if idx == endidx */
+	uint8_t *seq;	/* commands/data for the transaction */
+	union {
+	  hp_sdc_irqhook   *irqhook;	/* Callback, isr or tasklet context */
+	  struct semaphore *semaphore;	/* Semaphore to sleep on. */
+	} act;
+} hp_sdc_transaction;
+int hp_sdc_enqueue_transaction(hp_sdc_transaction *this);
+int hp_sdc_dequeue_transaction(hp_sdc_transaction *this);
+
+/* The HP_SDC_ACT* values are peculiar to this driver.
+ * Nuance: never HP_SDC_ACT_DATAIN | HP_SDC_ACT_DEALLOC, use another
+ * act to perform the dealloc.
+ */
+#define HP_SDC_ACT_PRECMD	0x01		/* Send a command first */
+#define HP_SDC_ACT_DATAREG	0x02		/* Set data registers */
+#define HP_SDC_ACT_DATAOUT	0x04		/* Send data bytes */
+#define HP_SDC_ACT_POSTCMD      0x08            /* Send command after */
+#define HP_SDC_ACT_DATAIN	0x10		/* Collect data after */
+#define HP_SDC_ACT_DURING	0x1f
+#define HP_SDC_ACT_SEMAPHORE    0x20            /* Raise semaphore after */
+#define HP_SDC_ACT_CALLBACK	0x40		/* Pass data to IRQ handler */
+#define HP_SDC_ACT_DEALLOC	0x80		/* Destroy transaction after */
+#define HP_SDC_ACT_AFTER	0xe0
+#define HP_SDC_ACT_DEAD		0x60		/* Act timed out. */
+
+/* Rest of the flags are straightforward representation of the SDC interface */
+#define HP_SDC_STATUS_IBF	0x02	/* Input buffer full */
+
+#define HP_SDC_STATUS_IRQMASK	0xf0	/* Bits containing "level 1" irq */
+#define HP_SDC_STATUS_PERIODIC  0x10    /* Periodic 10ms timer */
+#define HP_SDC_STATUS_USERTIMER 0x20    /* "Special purpose" timer */
+#define HP_SDC_STATUS_TIMER     0x30    /* Both PERIODIC and USERTIMER */
+#define HP_SDC_STATUS_REG	0x40	/* Data from an i8042 register */
+#define HP_SDC_STATUS_HILCMD    0x50	/* Command from HIL MLC */
+#define HP_SDC_STATUS_HILDATA   0x60	/* Data from HIL MLC */
+#define HP_SDC_STATUS_PUP	0x70	/* Sucessful power-up self test */
+#define HP_SDC_STATUS_KCOOKED	0x80	/* Key from cooked kbd */
+#define HP_SDC_STATUS_KRPG	0xc0	/* Key from Repeat Gen */
+#define HP_SDC_STATUS_KMOD_SUP	0x10	/* Shift key is up */
+#define HP_SDC_STATUS_KMOD_CUP	0x20	/* Control key is up */
+
+#define HP_SDC_NMISTATUS_FHS	0x40	/* NMI is a fast handshake irq */
+
+/* Internal i8042 registers (there are more, but they are not too useful). */
+
+#define HP_SDC_USE		0x02	/* Resource usage (including OB bit) */
+#define HP_SDC_IM		0x04	/* Interrupt mask */
+#define HP_SDC_CFG		0x11	/* Configuration register */
+#define HP_SDC_KBLANGUAGE	0x12	/* Keyboard language */
+
+#define HP_SDC_D0		0x70	/* General purpose data buffer 0 */
+#define HP_SDC_D1		0x71	/* General purpose data buffer 1 */
+#define HP_SDC_D2		0x72	/* General purpose data buffer 2 */
+#define HP_SDC_D3		0x73	/* General purpose data buffer 3 */
+#define HP_SDC_VT1		0x74	/* Timer for voice 1 */
+#define HP_SDC_VT2		0x75	/* Timer for voice 2 */
+#define HP_SDC_VT3		0x76	/* Timer for voice 3 */
+#define HP_SDC_VT4		0x77	/* Timer for voice 4 */
+#define HP_SDC_KBN		0x78	/* Which HIL devs are Nimitz */
+#define HP_SDC_KBC		0x79	/* Which HIL devs are cooked kbds */
+#define HP_SDC_LPS		0x7a	/* i8042's view of HIL status */
+#define HP_SDC_LPC		0x7b	/* i8042's view of HIL "control" */
+#define HP_SDC_RSV  		0x7c	/* Reserved "for testing" */
+#define HP_SDC_LPR		0x7d    /* i8042 count of HIL reconfigs */
+#define HP_SDC_XTD		0x7e    /* "Extended Configuration" register */
+#define HP_SDC_STR		0x7f    /* i8042 self-test result */
+
+/* Bitfields for above registers */
+#define HP_SDC_USE_LOOP		0x04	/* Command is currently on the loop. */
+
+#define HP_SDC_IM_MASK          0x1f    /* these bits not part of cmd/status */
+#define HP_SDC_IM_FH		0x10	/* Mask the fast handshake irq */
+#define HP_SDC_IM_PT		0x08	/* Mask the periodic timer irq */
+#define HP_SDC_IM_TIMERS	0x04	/* Mask the MT/DT/CT irq */
+#define HP_SDC_IM_RESET		0x02	/* Mask the reset key irq */
+#define HP_SDC_IM_HIL		0x01	/* Mask the HIL MLC irq */
+
+#define HP_SDC_CFG_ROLLOVER	0x08	/* WTF is "N-key rollover"? */
+#define HP_SDC_CFG_KBD		0x10	/* There is a keyboard */
+#define HP_SDC_CFG_NEW		0x20	/* Supports/uses HIL MLC */
+#define HP_SDC_CFG_KBD_OLD	0x03	/* keyboard code for non-HIL */
+#define HP_SDC_CFG_KBD_NEW	0x07	/* keyboard code from HIL autoconfig */
+#define HP_SDC_CFG_REV		0x40	/* Code revision bit */
+#define HP_SDC_CFG_IDPROM	0x80	/* IDPROM present in kbd (not HIL) */
+
+#define HP_SDC_LPS_NDEV		0x07	/* # devices autoconfigured on HIL */
+#define HP_SDC_LPS_ACSUCC	0x08	/* loop autoconfigured successfully */
+#define HP_SDC_LPS_ACFAIL	0x80	/* last loop autoconfigure failed */
+
+#define HP_SDC_LPC_APE_IPF	0x01	/* HIL MLC APE/IPF (autopoll) set */
+#define HP_SDC_LPC_ARCONERR	0x02	/* i8042 autoreconfigs loop on err */
+#define HP_SDC_LPC_ARCQUIET	0x03	/* i8042 doesn't report autoreconfigs*/
+#define HP_SDC_LPC_COOK		0x10	/* i8042 cooks devices in _KBN */
+#define HP_SDC_LPC_RC		0x80	/* causes autoreconfig */
+
+#define HP_SDC_XTD_REV		0x07	/* contains revision code */
+#define HP_SDC_XTD_REV_STRINGS(val, str) \
+switch (val) {						\
+	case 0x1: str = "1820-3712"; break;		\
+	case 0x2: str = "1820-4379"; break;		\
+	case 0x3: str = "1820-4784"; break;		\
+	default: str = "unknown";			\
+};
+#define HP_SDC_XTD_BEEPER	0x08	/* TI SN76494 beeper available */
+#define HP_SDC_XTD_BBRTC	0x20	/* OKI MSM-58321 BBRTC present */
+
+#define HP_SDC_CMD_LOAD_RT	0x31	/* Load real time (from 8042) */
+#define HP_SDC_CMD_LOAD_FHS	0x36	/* Load the fast handshake timer */
+#define HP_SDC_CMD_LOAD_MT	0x38	/* Load the match timer */
+#define HP_SDC_CMD_LOAD_DT	0x3B	/* Load the delay timer */
+#define HP_SDC_CMD_LOAD_CT	0x3E	/* Load the cycle timer */
+
+#define HP_SDC_CMD_SET_IM	0x40    /* 010xxxxx == set irq mask */
+
+/* The documents provided do not explicitly state that all registers betweem 
+ * 0x01 and 0x1f inclusive can be read by sending their register index as a 
+ * command, but this is implied and appears to be the case.
+ */
+#define HP_SDC_CMD_READ_RAM	0x00	/* Load from i8042 RAM (autoinc) */
+#define HP_SDC_CMD_READ_USE	0x02	/* Undocumented! Load from usage reg */
+#define HP_SDC_CMD_READ_IM	0x04	/* Load current interrupt mask */
+#define HP_SDC_CMD_READ_KCC	0x11	/* Load primary kbd config code */
+#define HP_SDC_CMD_READ_KLC	0x12	/* Load primary kbd language code */
+#define HP_SDC_CMD_READ_T1	0x13	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T2	0x14	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T3	0x15	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T4	0x16	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_T5	0x17	/* Load timer output buffer byte 1 */
+#define HP_SDC_CMD_READ_D0	0xf0	/* Load from i8042 RAM location 0x70 */
+#define HP_SDC_CMD_READ_D1	0xf1	/* Load from i8042 RAM location 0x71 */
+#define HP_SDC_CMD_READ_D2	0xf2	/* Load from i8042 RAM location 0x72 */
+#define HP_SDC_CMD_READ_D3	0xf3	/* Load from i8042 RAM location 0x73 */
+#define HP_SDC_CMD_READ_VT1	0xf4	/* Load from i8042 RAM location 0x74 */
+#define HP_SDC_CMD_READ_VT2	0xf5	/* Load from i8042 RAM location 0x75 */
+#define HP_SDC_CMD_READ_VT3	0xf6	/* Load from i8042 RAM location 0x76 */
+#define HP_SDC_CMD_READ_VT4	0xf7	/* Load from i8042 RAM location 0x77 */
+#define HP_SDC_CMD_READ_KBN	0xf8	/* Load from i8042 RAM location 0x78 */
+#define HP_SDC_CMD_READ_KBC	0xf9	/* Load from i8042 RAM location 0x79 */
+#define HP_SDC_CMD_READ_LPS	0xfa	/* Load from i8042 RAM location 0x7a */
+#define HP_SDC_CMD_READ_LPC	0xfb	/* Load from i8042 RAM location 0x7b */
+#define HP_SDC_CMD_READ_RSV	0xfc	/* Load from i8042 RAM location 0x7c */
+#define HP_SDC_CMD_READ_LPR	0xfd	/* Load from i8042 RAM location 0x7d */
+#define HP_SDC_CMD_READ_XTD	0xfe	/* Load from i8042 RAM location 0x7e */
+#define HP_SDC_CMD_READ_STR	0xff	/* Load from i8042 RAM location 0x7f */
+
+#define HP_SDC_CMD_SET_ARD	0xA0	/* Set emulated autorepeat delay */
+#define HP_SDC_CMD_SET_ARR	0xA2	/* Set emulated autorepeat rate */
+#define HP_SDC_CMD_SET_BELL	0xA3	/* Set voice 3 params for "beep" cmd */
+#define HP_SDC_CMD_SET_RPGR	0xA6	/* Set "RPG" irq rate (doesn't work) */
+#define HP_SDC_CMD_SET_RTMS	0xAD	/* Set the RTC time (milliseconds) */
+#define HP_SDC_CMD_SET_RTD	0xAF	/* Set the RTC time (days) */
+#define HP_SDC_CMD_SET_FHS	0xB2	/* Set fast handshake timer */
+#define HP_SDC_CMD_SET_MT	0xB4	/* Set match timer */
+#define HP_SDC_CMD_SET_DT	0xB7	/* Set delay timer */
+#define HP_SDC_CMD_SET_CT	0xBA	/* Set cycle timer */
+#define HP_SDC_CMD_SET_RAMP	0xC1	/* Reset READ_RAM autoinc counter */
+#define HP_SDC_CMD_SET_D0	0xe0	/* Load to i8042 RAM location 0x70 */
+#define HP_SDC_CMD_SET_D1	0xe1	/* Load to i8042 RAM location 0x71 */
+#define HP_SDC_CMD_SET_D2	0xe2	/* Load to i8042 RAM location 0x72 */
+#define HP_SDC_CMD_SET_D3	0xe3	/* Load to i8042 RAM location 0x73 */
+#define HP_SDC_CMD_SET_VT1	0xe4	/* Load to i8042 RAM location 0x74 */
+#define HP_SDC_CMD_SET_VT2	0xe5	/* Load to i8042 RAM location 0x75 */
+#define HP_SDC_CMD_SET_VT3	0xe6	/* Load to i8042 RAM location 0x76 */
+#define HP_SDC_CMD_SET_VT4	0xe7	/* Load to i8042 RAM location 0x77 */
+#define HP_SDC_CMD_SET_KBN	0xe8	/* Load to i8042 RAM location 0x78 */
+#define HP_SDC_CMD_SET_KBC	0xe9	/* Load to i8042 RAM location 0x79 */
+#define HP_SDC_CMD_SET_LPS	0xea	/* Load to i8042 RAM location 0x7a */
+#define HP_SDC_CMD_SET_LPC	0xeb	/* Load to i8042 RAM location 0x7b */
+#define HP_SDC_CMD_SET_RSV	0xec	/* Load to i8042 RAM location 0x7c */
+#define HP_SDC_CMD_SET_LPR	0xed	/* Load to i8042 RAM location 0x7d */
+#define HP_SDC_CMD_SET_XTD	0xee	/* Load to i8042 RAM location 0x7e */
+#define HP_SDC_CMD_SET_STR	0xef	/* Load to i8042 RAM location 0x7f */
+
+#define HP_SDC_CMD_DO_RTCW	0xc2	/* i8042 RAM 0x70 --> RTC */
+#define HP_SDC_CMD_DO_RTCR	0xc3	/* RTC[0x70 0:3] --> irq/status/data */
+#define HP_SDC_CMD_DO_BEEP	0xc4	/* i8042 RAM 0x70-74  --> beeper,VT3 */
+#define HP_SDC_CMD_DO_HIL	0xc5	/* i8042 RAM 0x70-73 --> 
+					   HIL MLC R0,R1 i8042 HIL watchdog */
+
+/* Values used to (de)mangle input/output to/from the HIL MLC */
+#define HP_SDC_DATA		0x40	/* Data from an 8042 register */
+#define HP_SDC_HIL_CMD		0x50	/* Data from HIL MLC R1/8042 */
+#define HP_SDC_HIL_R1MASK	0x0f	/* Contents of HIL MLC R1 0:3 */
+#define HP_SDC_HIL_AUTO		0x10	/* Set if POL results from i8042 */   
+#define HP_SDC_HIL_ISERR	0x80	/* Has meaning as in next 4 values */
+#define HP_SDC_HIL_RC_DONE	0x80	/* i8042 auto-configured loop */
+#define HP_SDC_HIL_ERR		0x81	/* HIL MLC R2 had a bit set */
+#define HP_SDC_HIL_TO		0x82	/* i8042 HIL watchdog expired */
+#define HP_SDC_HIL_RC		0x84	/* i8042 is auto-configuring loop */
+#define HP_SDC_HIL_DAT		0x60	/* Data from HIL MLC R0 */
+
+
+typedef struct {
+	rwlock_t	ibf_lock;
+	rwlock_t	lock;		/* user/tasklet lock */
+	rwlock_t	rtq_lock;	/* isr/tasklet lock */
+	rwlock_t	hook_lock;	/* isr/user lock for handler add/del */
+
+	unsigned int	irq, nmi;	/* Our IRQ lines */
+	unsigned long	base_io, status_io, data_io; /* Our IO ports */
+
+	uint8_t		im;		/* Interrupt mask */
+	int		set_im; 	/* Interrupt mask needs to be set. */
+
+	int		ibf;		/* Last known status of IBF flag */
+	uint8_t		wi;		/* current i8042 write index */
+	uint8_t		r7[4];          /* current i8042[0x70 - 0x74] values */
+	uint8_t		r11, r7e;	/* Values from version/revision regs */
+
+	hp_sdc_irqhook	*timer, *reg, *hil, *pup, *cooked;
+
+#define HP_SDC_QUEUE_LEN 16
+	hp_sdc_transaction *tq[HP_SDC_QUEUE_LEN]; /* All pending read/writes */
+
+	int		rcurr, rqty;	/* Current read transact in process */
+	struct timeval	rtv;		/* Time when current read started */
+	int		wcurr;		/* Current write transact in process */
+
+	int		dev_err;	/* carries status from registration */
+#if defined(__hppa__)
+	struct parisc_device	*dev;
+#elif defined(__mc68000__)
+	void		*dev;
+#else
+#error No support for device registration on this arch yet.
+#endif
+
+	struct timer_list kicker;	/* Keeps below task alive */
+	struct tasklet_struct	task;
+
+} hp_i8042_sdc;
+
+#endif /* _LINUX_HP_SDC_H */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/input.h parisc-2.6-bk/include/linux/input.h
--- linux-2.6.10-rc1-bk13/include/linux/input.h	Wed Nov  3 05:57:50 2004
+++ parisc-2.6-bk/include/linux/input.h	Wed Nov  3 06:19:22 2004
@@ -610,6 +610,7 @@ struct input_absinfo {
 #define BUS_ADB			0x17
 #define BUS_I2C			0x18
 #define BUS_HOST		0x19
+#define BUS_GSC			0x1A
 
 /*
  * Values describing the status of an effect
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/pci.h parisc-2.6-bk/include/linux/pci.h
--- linux-2.6.10-rc1-bk13/include/linux/pci.h	Wed Nov  3 05:57:50 2004
+++ parisc-2.6-bk/include/linux/pci.h	Wed Nov  3 06:19:22 2004
@@ -989,31 +989,33 @@ static inline char *pci_name(struct pci_
  */
 
 struct pci_fixup {
-	u16 vendor, device;			/* You can use PCI_ANY_ID here of course */
+	u16 vendor, device;	/* You can use PCI_ANY_ID here of course */
 	void (*hook)(struct pci_dev *dev);
 };
 
 enum pci_fixup_pass {
-	pci_fixup_header,	/* Called immediately after reading configuration header */
+	pci_fixup_early,	/* Before probing BARs */
+	pci_fixup_header,	/* After reading configuration header */
 	pci_fixup_final,	/* Final phase of device fixups */
 	pci_fixup_enable,	/* pci_enable_device() time */
 };
 
 /* Anonymous variables would be nice... */
-#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)					\
-	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
-	__attribute__((__section__(".pci_fixup_header"))) = {				\
-		vendor, device, hook };
-
-#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)				\
-	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
-	__attribute__((__section__(".pci_fixup_final"))) = {				\
-		vendor, device, hook };
-
-#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)				\
-	static struct pci_fixup __pci_fixup_##vendor##device##hook __attribute_used__	\
-	__attribute__((__section__(".pci_fixup_enable"))) = {				\
-		vendor, device, hook };
+#define DECLARE_PCI_FIXUP_SECTION(section, name, vendor, device, hook)	\
+	static struct pci_fixup __pci_fixup_##name __attribute_used__	\
+	__attribute__((__section__(#section))) = { vendor, device, hook };
+#define DECLARE_PCI_FIXUP_EARLY(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_early,			\
+			vendor##device##hook, vendor, device, hook)
+#define DECLARE_PCI_FIXUP_HEADER(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_header,			\
+			vendor##device##hook, vendor, device, hook)
+#define DECLARE_PCI_FIXUP_FINAL(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_final,			\
+			vendor##device##hook, vendor, device, hook)
+#define DECLARE_PCI_FIXUP_ENABLE(vendor, device, hook)			\
+	DECLARE_PCI_FIXUP_SECTION(.pci_fixup_enable,			\
+			vendor##device##hook, vendor, device, hook)
 
 
 void pci_fixup_device(enum pci_fixup_pass pass, struct pci_dev *dev);
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/serial_core.h parisc-2.6-bk/include/linux/serial_core.h
--- linux-2.6.10-rc1-bk13/include/linux/serial_core.h	Wed Nov  3 05:57:50 2004
+++ parisc-2.6-bk/include/linux/serial_core.h	Wed Nov  3 06:19:23 2004
@@ -91,6 +91,8 @@
 /* MPC52xx type numbers */
 #define PORT_MPC52xx	59
 
+#define SERIAL_IRQ_NONE -1
+
 #ifdef __KERNEL__
 
 #include <linux/config.h>
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/include/linux/signal.h parisc-2.6-bk/include/linux/signal.h
--- linux-2.6.10-rc1-bk13/include/linux/signal.h	Fri Oct 22 15:38:39 2004
+++ parisc-2.6-bk/include/linux/signal.h	Wed Nov  3 06:19:23 2004
@@ -220,6 +220,9 @@ struct pt_regs;
 extern int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie);
 #endif
 
+int copy_siginfo_from_user(siginfo_t *to, siginfo_t __user *from);
+int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from);
+
 #endif /* __KERNEL__ */
 
 #endif /* _LINUX_SIGNAL_H */
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/ipc/compat_mq.c parisc-2.6-bk/ipc/compat_mq.c
--- linux-2.6.10-rc1-bk13/ipc/compat_mq.c	Fri Oct 22 15:38:54 2004
+++ parisc-2.6-bk/ipc/compat_mq.c	Wed Nov  3 06:19:24 2004
@@ -7,6 +7,7 @@
  */
 
 #include <linux/compat.h>
+#include <linux/compat_siginfo.h>
 #include <linux/fs.h>
 #include <linux/kernel.h>
 #include <linux/mqueue.h>
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/Makefile parisc-2.6-bk/kernel/Makefile
--- linux-2.6.10-rc1-bk13/kernel/Makefile	Wed Nov  3 05:57:51 2004
+++ parisc-2.6-bk/kernel/Makefile	Wed Nov  3 06:19:24 2004
@@ -17,7 +17,7 @@ obj-$(CONFIG_MODULES) += module.o
 obj-$(CONFIG_KALLSYMS) += kallsyms.o
 obj-$(CONFIG_PM) += power/
 obj-$(CONFIG_BSD_PROCESS_ACCT) += acct.o
-obj-$(CONFIG_COMPAT) += compat.o
+obj-$(CONFIG_COMPAT) += compat.o compat_signal.o
 obj-$(CONFIG_IKCONFIG) += configs.o
 obj-$(CONFIG_IKCONFIG_PROC) += configs.o
 obj-$(CONFIG_STOP_MACHINE) += stop_machine.o
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/compat.c parisc-2.6-bk/kernel/compat.c
--- linux-2.6.10-rc1-bk13/kernel/compat.c	Fri Oct 22 15:39:19 2004
+++ parisc-2.6-bk/kernel/compat.c	Wed Nov  3 06:19:24 2004
@@ -13,6 +13,7 @@
 
 #include <linux/linkage.h>
 #include <linux/compat.h>
+#include <linux/compat_siginfo.h>
 #include <linux/errno.h>
 #include <linux/time.h>
 #include <linux/signal.h>
@@ -484,7 +485,7 @@ static int put_compat_itimerspec(struct 
 	return 0;
 } 
 
-long compat_timer_settime(timer_t timer_id, int flags, 
+long compat_sys_timer_settime(timer_t timer_id, int flags, 
 			  struct compat_itimerspec __user *new, 
 			  struct compat_itimerspec __user *old)
 { 
@@ -507,7 +508,7 @@ long compat_timer_settime(timer_t timer_
 	return err;
 } 
 
-long compat_timer_gettime(timer_t timer_id,
+long compat_sys_timer_gettime(timer_t timer_id,
 		struct compat_itimerspec __user *setting)
 { 
 	long err;
@@ -524,7 +525,7 @@ long compat_timer_gettime(timer_t timer_
 	return err;
 } 
 
-long compat_clock_settime(clockid_t which_clock,
+long compat_sys_clock_settime(clockid_t which_clock,
 		struct compat_timespec __user *tp)
 {
 	long err;
@@ -541,7 +542,7 @@ long compat_clock_settime(clockid_t whic
 	return err;
 } 
 
-long compat_clock_gettime(clockid_t which_clock,
+long compat_sys_clock_gettime(clockid_t which_clock,
 		struct compat_timespec __user *tp)
 {
 	long err;
@@ -558,7 +559,7 @@ long compat_clock_gettime(clockid_t whic
 	return err;
 } 
 
-long compat_clock_getres(clockid_t which_clock,
+long compat_sys_clock_getres(clockid_t which_clock,
 		struct compat_timespec __user *tp)
 {
 	long err;
@@ -575,7 +576,7 @@ long compat_clock_getres(clockid_t which
 	return err;
 } 
 
-long compat_clock_nanosleep(clockid_t which_clock, int flags,
+long compat_sys_clock_nanosleep(clockid_t which_clock, int flags,
 			    struct compat_timespec __user *rqtp,
 			    struct compat_timespec __user *rmtp)
 {
@@ -600,6 +601,26 @@ long compat_clock_nanosleep(clockid_t wh
 
 /* timer_create is architecture specific because it needs sigevent conversion */
 
+long compat_sys_timer_create(clockid_t which_clock,
+			     compat_sigevent_t __user *timer_event_spec,
+			     compat_timer_t __user * created_timer_id)
+{
+	sigevent_t kevent;
+	mm_segment_t old_fs = get_fs();
+	long ret;
+
+	if (timer_event_spec != NULL)
+		if (compat_copy_sigevent_from_user(&kevent, timer_event_spec) != 0)
+			return -EFAULT;
+
+	set_fs(KERNEL_DS);
+	ret = sys_timer_create(which_clock, timer_event_spec ? (sigevent_t __user *)&kevent : NULL, created_timer_id);
+	set_fs(old_fs);
+
+	return ret;
+}
+
+
 long compat_get_bitmap(unsigned long *mask, compat_ulong_t __user *umask,
 		       unsigned long bitmap_size)
 {
@@ -677,6 +698,40 @@ long compat_put_bitmap(compat_ulong_t __
 			m >>= 4*sizeof(um);
 		}
 	}
+
+	return 0;
+}
+
+asmlinkage int compat_sys_waitid(int which, pid_t pid,
+				 compat_siginfo_t __user *infop, int options,
+				 struct compat_rusage __user *ru)
+{
+  	long ret;
+	siginfo_t ksiginfo;
+	struct rusage kru;
+	mm_segment_t old_fs = get_fs();
+	
+	memset(&ksiginfo, 0, sizeof(ksiginfo));
+
+	set_fs(KERNEL_DS);
+	ret = sys_waitid(which, pid, (siginfo_t __user *)&ksiginfo, options, (struct rusage __user *)&kru);
+	set_fs(old_fs);
+
+	/* If there was an error don't bother copying siginfo */
+	if (ret < 0 || ksiginfo.si_signo == 0)
+		return ret;
+
+	if (ru) {
+		ret = put_compat_rusage(&kru, ru);
+		if (ret)
+			return ret;
+	}
+
+	/* Tell copy_siginfo_to_user that it was __SI_CHLD */
+	ksiginfo.si_code |= __SI_CHLD;
+	
+	if (compat_copy_siginfo_to_user(infop, &ksiginfo) != 0)
+		return -EFAULT;
 
 	return 0;
 }
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/compat_signal.c parisc-2.6-bk/kernel/compat_signal.c
--- linux-2.6.10-rc1-bk13/kernel/compat_signal.c	Wed Dec 31 17:00:00 1969
+++ parisc-2.6-bk/kernel/compat_signal.c	Wed Nov  3 06:12:59 2004
@@ -0,0 +1,244 @@
+/*
+ *  Copyright (C) 2003 Carlos O'Donell
+ * 
+ *  2003-12-20  Carlos O'Donell
+ *              Copied linux/kernel/compat_signal.c (copy_siginfo_to_user)
+ *              and modified to use compat_siginfo_t for thunking down to
+ *              32-bit userspace from a 64-bit kernel.
+ *              
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
+ * NON INFRINGEMENT.  See the GNU General Public License for more
+ * details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA 
+ *
+ */
+
+#include <linux/compat_siginfo.h>
+#include <asm/errno.h>
+#include <asm/uaccess.h>
+#include <asm/siginfo.h>
+
+#ifndef HAVE_ARCH_COMPAT_COPY_SIGINFO_TO_USER
+int compat_copy_siginfo_to_user(compat_siginfo_t __user *to, siginfo_t *from)
+{
+	int err;
+	compat_siginfo_t compat_from;	
+
+	if (!access_ok (VERIFY_WRITE, to, sizeof(compat_siginfo_t)))
+		return -EFAULT;
+	
+	/*
+	 * If you change compat_siginfo_t structure *or* siginfo_t, 
+	 * please be sure this code is fixed accordingly.
+	 * It should never copy any pad contained in the structure
+	 * to avoid security leaks, but must copy the generic
+	 * 3 ints plus the relevant union member.
+	 */
+
+	/* Convert structure, don't leak anything in the copy */
+	memset(&compat_from,'\0',sizeof(compat_siginfo_t));
+
+        /* Always copy si_signo, si_errno, and si_code */
+	compat_from.si_signo = (compat_int_t)(from->si_signo);
+	compat_from.si_errno = (compat_int_t)(from->si_errno);
+	/* si_code is only a (short) value, remove kernel bits. */
+	compat_from.si_code = (short)(from->si_code);
+        
+	err = __put_user(compat_from.si_signo, &to->si_signo);
+	err |= __put_user(compat_from.si_errno, &to->si_errno);
+	err |= __put_user(compat_from.si_code, &to->si_code);
+
+        /* siginfo_t came from userspace, so it is the right
+         * size, no need for conversion
+         */        
+	if (from->si_code < 0) {
+		return __copy_to_user(&to->_sifields._pad, 
+                                      &from->_sifields._pad, 
+                                      SI_COMPAT_PAD_SIZE)
+			? -EFAULT : 0;
+        }
+	
+	switch (from->si_code & __SI_MASK) {
+	case __SI_KILL:
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		break;
+	case __SI_TIMER:
+		compat_from.si_pid = (compat_timer_t)(from->si_tid);
+		compat_from.si_overrun = (compat_int_t)(from->si_overrun);
+		compat_from.si_ptr = (compat_uptr_t)((u64)(from->si_ptr) & 0xffffffffUL);
+		err |= __put_user(compat_from.si_tid, &to->si_tid);
+		err |= __put_user(compat_from.si_overrun, &to->si_overrun);
+		err |= __put_user(compat_from.si_ptr, &to->si_ptr);
+		break;
+	case __SI_POLL:
+		compat_from.si_band = (__ARCH_SI_COMPAT_BAND_T)(from->si_band);
+		compat_from.si_fd = (compat_int_t)(from->si_fd);
+		err |= __put_user(compat_from.si_band, &to->si_band);
+		err |= __put_user(compat_from.si_fd, &to->si_fd);
+		break;
+	case __SI_FAULT:
+		compat_from.si_addr = (compat_uptr_t)((u64)(from->si_addr) & 0xffffffffUL);
+		err |= __put_user(compat_from.si_addr, &to->si_addr);
+#ifdef __ARCH_SI_COMPAT_TRAPNO
+		compat_from.si_trapno = (compat_int_t)(from->si_addr);
+		err |= __put_user(compat_from.si_trapno, &to->si_trapno);
+#endif
+		break;
+	case __SI_CHLD:
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		compat_from.si_status = (compat_int_t)(from->si_status);
+		compat_from.si_utime = (compat_clock_t)(from->si_utime);
+		compat_from.si_stime = (compat_clock_t)(from->si_stime);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		err |= __put_user(compat_from.si_status, &to->si_status);
+		err |= __put_user(compat_from.si_utime, &to->si_utime);
+		err |= __put_user(compat_from.si_stime, &to->si_stime);
+		break;
+	case __SI_RT: /* This is not generated by the kernel as of now. */
+	case __SI_MESGQ: /* But this is */
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		compat_from.si_int = (compat_int_t)(from->si_int);
+		compat_from.si_ptr = (compat_uptr_t)((u64)(from->si_ptr) & 0xffffffffUL);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		err |= __put_user(compat_from.si_int, &to->si_int);
+		err |= __put_user(compat_from.si_ptr, &to->si_ptr);
+		break;
+	default: /* this is just in case for now ... */
+		compat_from.si_pid = (compat_pid_t)(from->si_pid);
+		compat_from.si_uid = (__ARCH_SI_COMPAT_UID_T)(from->si_uid);
+		err |= __put_user(compat_from.si_pid, &to->si_pid);
+		err |= __put_user(compat_from.si_uid, &to->si_uid);
+		break;
+	}
+	return err;
+}
+#endif
+
+#ifndef HAVE_ARCH_COPY_SIGINFO_FROM_USER
+int compat_copy_siginfo_from_user(siginfo_t *to, compat_siginfo_t __user *from)
+{
+	int err;
+        u64 scratch;
+
+	if (!access_ok (VERIFY_READ, from, sizeof(compat_siginfo_t)))
+		return -EFAULT;
+	
+	/*
+	 * If you change compat_siginfo_t structure *or* siginfo_t, 
+	 * please be sure this code is fixed accordingly.
+	 */
+
+        /* Always copy si_signo, si_errno, and si_code */
+	err = __get_user(to->si_signo, &from->si_signo);
+	err |= __get_user(to->si_errno, &from->si_errno);
+	err |= __get_user(to->si_code, &from->si_code);
+        
+        /* siginfo_t came from userspace, so it is the right
+         * size, no need for conversion
+         */        
+	if (to->si_code < 0) {
+		return __copy_from_user(&to->_sifields._pad, 
+                                        &from->_sifields._pad, 
+                                        SI_COMPAT_PAD_SIZE)
+			? -EFAULT : 0;
+        }
+	
+	switch (to->si_code & __SI_MASK) {
+	case __SI_KILL:
+		err |= __get_user(to->si_pid, &from->si_pid);
+		err |= __get_user(to->si_uid, &from->si_uid);
+		break;
+	case __SI_TIMER:
+		err |= __get_user(to->si_tid, &from->si_tid);
+		err |= __get_user(to->si_overrun, &from->si_overrun);
+		err |= __get_user(scratch, &from->si_ptr);
+                to->si_ptr = (u64*)scratch;                
+		break;
+	case __SI_POLL:
+		err |= __get_user(to->si_band, &from->si_band);
+		err |= __get_user(to->si_fd, &from->si_fd);
+		break;
+	case __SI_FAULT:
+		err |= __get_user(scratch, &from->si_addr);
+                to->si_addr = (u64*)scratch;
+#ifdef __ARCH_SI_COMPAT_TRAPNO
+		err |= __get_user(to->si_trapno, &from->si_trapno);
+#endif
+		break;
+	case __SI_CHLD:
+		err |= __get_user(to->si_pid, &from->si_pid);
+		err |= __get_user(to->si_uid, &from->si_uid);
+		err |= __get_user(to->si_status, &from->si_status);
+		err |= __get_user(to->si_utime, &from->si_utime);
+		err |= __get_user(to->si_stime, &from->si_stime);
+		break;
+	case __SI_RT: /* This is not generated by the kernel as of now. */
+	case __SI_MESGQ: /* But this is */
+		err |= __get_user(to->si_pid, &from->si_pid);
+		err |= __get_user(to->si_uid, &from->si_uid);
+		err |= __get_user(to->si_int, &from->si_int);
+		err |= __get_user(scratch, &from->si_ptr);
+                to->si_ptr = (u64*)scratch;
+		break;
+	default: /* this is just in case for now ... */
+		err |= __get_user(to->si_pid, &from->si_pid);
+		err |= __get_user(to->si_uid, &from->si_uid);
+		break;
+	}
+	return err;
+}
+#endif
+
+#ifndef HAVE_ARCH_COPY_SIGEVENT_FROM_USER
+int compat_copy_sigevent_from_user(sigevent_t *to, compat_sigevent_t __user *from)
+{
+	int err;
+	u64 scratch;
+	
+	/* copy sigval_t sigev_value 
+	 	int_t sival_int		(same)
+	 	uptr_t sival_ptr	(32 vs 64)*/
+	err = __get_user(to->sigev_value.sival_int, 
+	    		 &from->sigev_value.sival_int);
+	err |= __get_user(scratch, &from->sigev_value.sival_ptr);
+	to->sigev_value.sival_ptr = (u64 *)scratch;
+	
+	/* copy int_t sigev_signo 	(same)*/
+	err |= __get_user(to->sigev_signo, &from->sigev_signo);
+	
+	/* copy int_t sigev_notify	(same)*/
+	err |= __get_user(to->sigev_notify, &from->sigev_notify);
+
+	/* never copy _sigev_un padding */
+
+	/* copy int_t _tid 		(same),
+	   good_sigevent() uses this value of */
+	err |= __get_user(to->sigev_notify_thread_id, &from->sigev_notify_thread_id);
+	
+	/* XXX: Do not copy these, they aren't used by
+	   anyone. We would need to distinguish the uses of the union.
+	   copy _sigev_thread
+	  	uptr_t _function	(32 vs 64)
+	  	uptr_t _attribute	(32 vs 64)*/
+	
+	return err;
+}
+#endif
+
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/printk.c parisc-2.6-bk/kernel/printk.c
--- linux-2.6.10-rc1-bk13/kernel/printk.c	Fri Oct 22 15:40:29 2004
+++ parisc-2.6-bk/kernel/printk.c	Wed Nov  3 06:19:24 2004
@@ -92,8 +92,8 @@ static int log_buf_len = __LOG_BUF_LEN;
  * must be masked before subscripting
  */
 static unsigned long log_start;	/* Index into log_buf: next char to be read by syslog() */
-static unsigned long con_start;	/* Index into log_buf: next char to be sent to consoles */
-static unsigned long log_end;	/* Index into log_buf: most-recently-written-char + 1 */
+unsigned long con_start;	/* Index into log_buf: next char to be sent to consoles */
+unsigned long log_end;	/* Index into log_buf: most-recently-written-char + 1 */
 static unsigned long logged_chars; /* Number of chars produced since last read+clear operation */
 
 /*
@@ -789,6 +789,11 @@ void register_console(struct console * c
 
 	if (!(console->flags & CON_ENABLED))
 		return;
+
+	if (console_drivers && (console_drivers->flags & CON_BOOT)) {
+		unregister_console(console_drivers);
+		console->flags &= ~CON_PRINTBUFFER;
+	}
 
 	/*
 	 *	Put this console in the list - keep the
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/ptrace.c parisc-2.6-bk/kernel/ptrace.c
--- linux-2.6.10-rc1-bk13/kernel/ptrace.c	Wed Nov  3 05:57:51 2004
+++ parisc-2.6-bk/kernel/ptrace.c	Wed Nov  3 06:19:25 2004
@@ -328,7 +328,7 @@ static int ptrace_setsiginfo(struct task
 {
 	if (child->last_siginfo == NULL)
 		return -EINVAL;
-	if (copy_from_user(child->last_siginfo, data, sizeof (siginfo_t)) != 0)
+	if (copy_siginfo_from_user(child->last_siginfo, data) != 0)
 		return -EFAULT;
 	return 0;
 }
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/resource.c parisc-2.6-bk/kernel/resource.c
--- linux-2.6.10-rc1-bk13/kernel/resource.c	Wed Nov  3 05:57:51 2004
+++ parisc-2.6-bk/kernel/resource.c	Wed Nov  3 06:19:26 2004
@@ -181,6 +181,8 @@ static int __release_resource(struct res
 {
 	struct resource *tmp, **p;
 
+	BUG_ON(old->child);
+
 	p = &old->parent->child;
 	for (;;) {
 		tmp = *p;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/signal.c parisc-2.6-bk/kernel/signal.c
--- linux-2.6.10-rc1-bk13/kernel/signal.c	Wed Nov  3 05:57:51 2004
+++ parisc-2.6-bk/kernel/signal.c	Wed Nov  3 06:19:26 2004
@@ -22,6 +22,7 @@
 #include <linux/security.h>
 #include <linux/syscalls.h>
 #include <linux/ptrace.h>
+#include <linux/compat_siginfo.h>
 #include <asm/param.h>
 #include <asm/uaccess.h>
 #include <asm/unistd.h>
@@ -2064,17 +2065,35 @@ sys_rt_sigpending(sigset_t __user *set, 
 	return do_sigpending(set, sigsetsize);
 }
 
+#ifndef HAVE_ARCH_COPY_SIGINFO_FROM_USER
+
+int copy_siginfo_from_user(siginfo_t *to, siginfo_t __user *from)
+{
+        if(is_compat_task(current))
+                return compat_copy_siginfo_from_user(to,(compat_siginfo_t __user *)from);
+  
+        return copy_from_user(&to, from, sizeof(siginfo_t));
+}
+
+#endif
+
 #ifndef HAVE_ARCH_COPY_SIGINFO_TO_USER
 
 int copy_siginfo_to_user(siginfo_t __user *to, siginfo_t *from)
 {
 	int err;
+	
+	/* Use compat_siginfo_t with 32-bit signals */
+	if(is_compat_task(current)){
+		return compat_copy_siginfo_to_user((compat_siginfo_t __user *)to,from);
+	}
 
 	if (!access_ok (VERIFY_WRITE, to, sizeof(siginfo_t)))
 		return -EFAULT;
 	if (from->si_code < 0)
 		return __copy_to_user(to, from, sizeof(siginfo_t))
 			? -EFAULT : 0;
+	
 	/*
 	 * If you change siginfo_t structure, please be sure
 	 * this code is fixed accordingly.
@@ -2311,7 +2330,7 @@ sys_rt_sigqueueinfo(int pid, int sig, si
 {
 	siginfo_t info;
 
-	if (copy_from_user(&info, uinfo, sizeof(siginfo_t)))
+	if (copy_siginfo_from_user(&info, uinfo))
 		return -EFAULT;
 
 	/* Not even root can pretend to send signals from the kernel.
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/kernel/sys_ni.c parisc-2.6-bk/kernel/sys_ni.c
--- linux-2.6.10-rc1-bk13/kernel/sys_ni.c	Wed Nov  3 05:57:51 2004
+++ parisc-2.6-bk/kernel/sys_ni.c	Wed Nov  3 08:18:49 2004
@@ -68,9 +68,9 @@ cond_syscall(compat_sys_mq_getsetattr)
 cond_syscall(sys_mbind)
 cond_syscall(sys_get_mempolicy)
 cond_syscall(sys_set_mempolicy)
-cond_syscall(compat_mbind)
-cond_syscall(compat_get_mempolicy)
-cond_syscall(compat_set_mempolicy)
+cond_syscall(compat_sys_mbind)
+cond_syscall(compat_sys_get_mempolicy)
+cond_syscall(compat_sys_set_mempolicy)
 cond_syscall(sys_add_key)
 cond_syscall(sys_request_key)
 cond_syscall(sys_keyctl)
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/mm/mempolicy.c parisc-2.6-bk/mm/mempolicy.c
--- linux-2.6.10-rc1-bk13/mm/mempolicy.c	Wed Nov  3 05:57:51 2004
+++ parisc-2.6-bk/mm/mempolicy.c	Wed Nov  3 06:19:26 2004
@@ -530,7 +530,7 @@ asmlinkage long sys_get_mempolicy(int __
 
 #ifdef CONFIG_COMPAT
 
-asmlinkage long compat_get_mempolicy(int __user *policy,
+asmlinkage long compat_sys_get_mempolicy(int __user *policy,
 				     compat_ulong_t __user *nmask,
 				     compat_ulong_t maxnode,
 				     compat_ulong_t addr, compat_ulong_t flags)
@@ -558,7 +558,7 @@ asmlinkage long compat_get_mempolicy(int
 	return err;
 }
 
-asmlinkage long compat_set_mempolicy(int mode, compat_ulong_t __user *nmask,
+asmlinkage long compat_sys_set_mempolicy(int mode, compat_ulong_t __user *nmask,
 				     compat_ulong_t maxnode)
 {
 	long err = 0;
@@ -581,7 +581,7 @@ asmlinkage long compat_set_mempolicy(int
 	return sys_set_mempolicy(mode, nm, nr_bits+1);
 }
 
-asmlinkage long compat_mbind(compat_ulong_t start, compat_ulong_t len,
+asmlinkage long compat_sys_mbind(compat_ulong_t start, compat_ulong_t len,
 			     compat_ulong_t mode, compat_ulong_t __user *nmask,
 			     compat_ulong_t maxnode, compat_ulong_t flags)
 {
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/mm/shmem.c parisc-2.6-bk/mm/shmem.c
--- linux-2.6.10-rc1-bk13/mm/shmem.c	Wed Nov  3 05:57:51 2004
+++ parisc-2.6-bk/mm/shmem.c	Wed Nov  3 06:30:33 2004
@@ -462,7 +462,7 @@ static void shmem_free_pages(struct list
 	} while (next);
 }
 
-static void shmem_truncate(struct inode *inode)
+/* static gcc-3.3 OPD bug - GGG */ void shmem_truncate(struct inode *inode)
 {
 	struct shmem_inode_info *info = SHMEM_I(inode);
 	unsigned long idx;
diff -urpNX dontdiff linux-2.6.10-rc1-bk13/usr/Makefile parisc-2.6-bk/usr/Makefile
--- linux-2.6.10-rc1-bk13/usr/Makefile	Wed Nov  3 05:57:53 2004
+++ parisc-2.6-bk/usr/Makefile	Wed Nov  3 06:19:30 2004
@@ -8,7 +8,7 @@ clean-files := initramfs_data.cpio.gz in
 # If you want a different list of files in the initramfs_data.cpio
 # then you can either overwrite the cpio_list in this directory
 # or set INITRAMFS_LIST to another filename.
-INITRAMFS_LIST := $(obj)/initramfs_list
+INITRAMFS_LIST := $(srctree)/$(obj)/initramfs_list
 
 # initramfs_data.o contains the initramfs_data.cpio.gz image.
 # The image is included using .incbin, a dependency which is not

