diff -u -r --new-file linux/Documentation/Configure.help ha/Documentation/Configure.help
--- linux/Documentation/Configure.help	Thu Nov 22 11:52:44 2001
+++ ha/Documentation/Configure.help	Thu Dec 13 13:04:17 2001
@@ -23938,6 +23938,741 @@
   would like kernel messages to be formatted into GDB $O packets so
   that GDB prints them as program output, say 'Y'.
 
+Kernel Event Reporting Broker support
+CONFIG_EVENT_BROKER
+  The kernel event broker drivers is an implementation of the many
+  subscribers to one sender eventing system.  It has been added to
+  support cPCI hot swap but may be useful for many other systems
+  also.
+
+  Select Y here if you wish to have it included.  The cPCI driver
+  will automatically set this config parameter.
+
+Compact PCI Bus Hot Swap Support
+CONFIG_CPCI_HOTSWAP
+  Most Compact PCI (cPCI) chassis are capable of insertion and removal
+  of devices while powered on.  This entails knowing many things about
+  the cPCI bus configuration.  Selecting this paramater enables the
+  core code to support this functionality and brings up a list of
+  supported configurations.
+
+  Select Y here if you wish to support Hot Swap on the cPCI busses.
+
+Host and Compact PCI Chassis Type
+CONFIG_MOT_GEN
+  This option selects the particular Host Slot CPU board support
+  and the paticular cPCI chassis support.
+
+  The CONFIG_MOT_GEN option selects functionality to enable either the
+  Motorola MPC750 (Mesquite) or CPV5350 CPU modules to perform hot insertion
+  and removal of cPCI boards.  It software selects between support
+  for the Motorola 82XX HA cPCI chassis series and support for standard
+  Hot Swap cPCI chassis scanned in decending order.
+
+  The CONFIG_ZT_5550 option selects functionality to enable the Ziatech
+  5550 Host slot CPU modules to perform hot insertion and removal of cPCI
+  boards.  It Currently configures the Ziatech 5083 cPCI HA chassis.
+
+  A menu with these selections will appear when CONFIG_CPCI_HOTSWAP has
+  been selected.  Choose the configuration of CPU and chassis desired.
+
+Compact PCI IO Sizes for 82XX chassis Slot 1
+CONFIG_MOT_82XX_SLOT1_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot one of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 2
+CONFIG_MOT_82XX_SLOT2_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot two of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 3
+CONFIG_MOT_82XX_SLOT3_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot three of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 4
+CONFIG_MOT_82XX_SLOT4_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot four of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 5
+CONFIG_MOT_82XX_SLOT5_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot five of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot  6
+CONFIG_MOT_82XX_SLOT6_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot six of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 11
+CONFIG_MOT_82XX_SLOT11_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot eleven of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 12
+CONFIG_MOT_82XX_SLOT12_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot twelve of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 13
+CONFIG_MOT_82XX_SLOT13_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot thirteen of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 14
+CONFIG_MOT_82XX_SLOT14_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot fourteen of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 15
+CONFIG_MOT_82XX_SLOT15_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot fifteen of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 82XX chassis Slot 16
+CONFIG_MOT_82XX_SLOT16_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot sixteen of a
+  Motorola 82XX cPCI chassis.  Space is indicated in kilobytes and must
+  be allocated on 4K boundries.  Each slot should not require more than
+  8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 1
+CONFIG_MOT_82XX_SLOT1_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  one of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 2
+CONFIG_MOT_82XX_SLOT2_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  two of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 3
+CONFIG_MOT_82XX_SLOT3_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  three of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 4
+CONFIG_MOT_82XX_SLOT4_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  four of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 5
+CONFIG_MOT_82XX_SLOT5_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  five of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 6
+CONFIG_MOT_82XX_SLOT6_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  six of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 11
+CONFIG_MOT_82XX_SLOT11_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  eleven of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 12
+CONFIG_MOT_82XX_SLOT12_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  twelve of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 13
+CONFIG_MOT_82XX_SLOT13_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  thirteen of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 14
+CONFIG_MOT_82XX_SLOT14_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  fourteen of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 15
+CONFIG_MOT_82XX_SLOT15_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  fifteen of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 82XX chassis Slot 16
+CONFIG_MOT_82XX_SLOT16_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot
+  sixteen of a Motorola 82XX cPCI chassis.  Space is indicated in megabytes
+  and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for Generic Hot Swap chassis Slot 1
+CONFIG_MOT_GEN_SLOT1_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot one of a
+  standard Hot Swap cPCI chassis with either a Motorola MCP750
+  or CPV5350 host slot CPU board.  Space is indicated in kilobytes and
+  must be allocated on 4K boundries.  Each slot should not require more
+  than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for Generic Hot Swap chassis Slot 2
+CONFIG_MOT_GEN_SLOT2_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot two of a
+  standard Hot Swap cPCI chassis with either a Motorola MCP750
+  or CPV5350 host slot CPU board.  Space is indicated in kilobytes and
+  must be allocated on 4K boundries.  Each slot should not require more
+  than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for Generic Hot Swap chassis Slot 3
+CONFIG_MOT_GEN_SLOT3_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot three of a
+  standard Hot Swap cPCI chassis with either a Motorola MCP750
+  or CPV5350 host slot CPU board.  Space is indicated in kilobytes and
+  must be allocated on 4K boundries.  Each slot should not require more
+  than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for Generic Hot Swap chassis Slot 4
+CONFIG_MOT_GEN_SLOT4_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot four of a
+  standard Hot Swap cPCI chassis with either a Motorola MCP750
+  or CPV5350 host slot CPU board.  Space is indicated in kilobytes and
+  must be allocated on 4K boundries.  Each slot should not require more
+  than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for Generic Hot Swap chassis Slot 5
+CONFIG_MOT_GEN_SLOT5_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot five of a
+  standard Hot Swap cPCI chassis with either a Motorola MCP750
+  or CPV5350 host slot CPU board.  Space is indicated in kilobytes and
+  must be allocated on 4K boundries.  Each slot should not require more
+  than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for Generic Hot Swap chassis Slot 6
+CONFIG_MOT_GEN_SLOT6_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot six of a
+  standard Hot Swap cPCI chassis with either a Motorola MCP750
+  or CPV5350 host slot CPU board.  Space is indicated in kilobytes and
+  must be allocated on 4K boundries.  Each slot should not require more
+  than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for Generic Hot Swap chassis Slot 7
+CONFIG_MOT_GEN_SLOT7_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot seven of a
+  standard Hot Swap cPCI chassis with either a Motorola MCP750
+  or CPV5350 host slot CPU board.  Space is indicated in kilobytes and
+  must be allocated on 4K boundries.  Each slot should not require more
+  than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for Generic Hot Swap chassis Slot 1
+CONFIG_MOT_GEN_SLOT1_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot one
+  of a standared Hot Swap cPCI chassis either a Motorola MCP750 or
+  CPV5350 host slot CPU board.  Space is indicated in megabytes and must
+  be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for Generic Hot Swap chassis Slot 2
+CONFIG_MOT_GEN_SLOT2_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot tow
+  of a standared Hot Swap cPCI chassis either a Motorola MCP750 or
+  CPV5350 host slot CPU board.  Space is indicated in megabytes and must
+  be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for Generic Hot Swap chassis Slot 3
+CONFIG_MOT_GEN_SLOT3_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot three
+  of a standared Hot Swap cPCI chassis either a Motorola MCP750 or
+  CPV5350 host slot CPU board.  Space is indicated in megabytes and must
+  be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for Generic Hot Swap chassis Slot 4
+CONFIG_MOT_GEN_SLOT4_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot four
+  of a standared Hot Swap cPCI chassis either a Motorola MCP750 or
+  CPV5350 host slot CPU board.  Space is indicated in megabytes and must
+  be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for Generic Hot Swap chassis Slot 5
+CONFIG_MOT_GEN_SLOT5_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot five
+  of a standared Hot Swap cPCI chassis either a Motorola MCP750 or
+  CPV5350 host slot CPU board.  Space is indicated in megabytes and must
+  be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for Generic Hot Swap chassis Slot 6
+CONFIG_MOT_GEN_SLOT6_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot six
+  of a standared Hot Swap cPCI chassis either a Motorola MCP750 or
+  CPV5350 host slot CPU board.  Space is indicated in megabytes and must
+  be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for Generic Hot Swap chassis Slot 7
+CONFIG_MOT_GEN_SLOT7_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot seven
+  of a standared Hot Swap cPCI chassis either a Motorola MCP750 or
+  CPV5350 host slot CPU board.  Space is indicated in megabytes and must
+  be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 1
+CONFIG_ZIA_5083_SLOT1_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot one of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 2
+CONFIG_ZIA_5083_SLOT2_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot towof a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 3
+CONFIG_ZIA_5083_SLOT3_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot three of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 4
+CONFIG_ZIA_5083_SLOT4_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot four of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 5
+CONFIG_ZIA_5083_SLOT5_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot five of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 6
+CONFIG_ZIA_5083_SLOT6_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot six of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 11
+CONFIG_ZIA_5083_SLOT11_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot eleven of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 12
+CONFIG_ZIA_5083_SLOT12_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot twelve of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 13
+CONFIG_ZIA_5083_SLOT13_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot thirteen of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 14
+CONFIG_ZIA_5083_SLOT14_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot fourteen of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 15
+CONFIG_ZIA_5083_SLOT15_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot fifteen of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI IO Sizes for 5083 chassis Slot 16
+CONFIG_ZIA_5083_SLOT16_IO_SIZE
+  Select the amount of space to reserve for PCI IO on slot sixteen of a
+  Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.  Space
+  is indicated in kilobytes and must be allocated on 4K boundries.  Each
+  slot should not require more than 8K under most circumstance.
+
+  A limiting factor to watch for is allocating IO space on most Intel
+  X86 architectures.  The total IO space allocated to the cPCI bus
+  cannot exceed 48K.  On the Motorola and Ziatech HA chassis this leaves
+  only 4K of space for most cPCI slots.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 1
+CONFIG_ZIA_5083_SLOT1_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot one
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 2
+CONFIG_ZIA_5083_SLOT2_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot two
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 3
+CONFIG_ZIA_5083_SLOT3_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot three
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 4
+CONFIG_ZIA_5083_SLOT4_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot four
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 5
+CONFIG_ZIA_5083_SLOT5_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot five
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 6
+CONFIG_ZIA_5083_SLOT6_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot six
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 11
+CONFIG_ZIA_5083_SLOT11_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot eleven
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 12
+CONFIG_ZIA_5083_SLOT12_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot twelve
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 13
+CONFIG_ZIA_5083_SLOT13_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot thirteen
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 14
+CONFIG_ZIA_5083_SLOT14_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot fourteen
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 15
+CONFIG_ZIA_5083_SLOT15_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot fifteen
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+Compact PCI Memory Sizes for 5083 chassis Slot 16
+CONFIG_ZIA_5083_SLOT16_MEM_SIZE
+  Select the amount of space to reserve for PCI Memory BARs on slot sixteen
+  of a Ziatech 5083 cPCI chassis with a Ziatech 5550 host slot CPU board.
+  Space is indicated in megabytes and must be allocated on 1M boundries.
+
+  Set this selection to the value you wish to reserve.
+
+
 #
 # A couple of things I keep forgetting:
 #   capitalize: AppleTalk, Ethernet, DOS, DMA, FAT, FTP, Internet,
diff -u -r --new-file linux/Makefile ha/Makefile
--- linux/Makefile	Mon Nov 26 06:29:17 2001
+++ ha/Makefile	Thu Dec 13 13:04:49 2001
@@ -185,6 +185,9 @@
 DRIVERS-$(CONFIG_BLUEZ) += drivers/bluetooth/bluetooth.o
 DRIVERS-$(CONFIG_HOTPLUG_PCI) += drivers/hotplug/vmlinux-obj.o
 
+DRIVERS-$(CONFIG_CPCI_HOTSWAP) += drivers/ha/cpci/cpci.o
+DRIVERS-$(CONFIG_EVENT_BROKER) += drivers/ha/event/event.o
+
 DRIVERS := $(DRIVERS-y)
 
 
diff -u -r --new-file linux/arch/i386/config.in ha/arch/i386/config.in
--- linux/arch/i386/config.in	Mon Nov 12 12:58:08 2001
+++ ha/arch/i386/config.in	Thu Dec 13 13:06:09 2001
@@ -392,6 +392,12 @@
 
 source drivers/usb/Config.in
 
+mainmenu_option next_comment
+comment 'High Availability features'
+bool 'Kernel Event Reporting Broker support' CONFIG_EVENT_BROKER
+source drivers/ha/Config.in
+endmenu
+
 if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
    source net/bluetooth/Config.in
 fi
diff -u -r --new-file linux/arch/i386/kernel/pci-pc.c ha/arch/i386/kernel/pci-pc.c
--- linux/arch/i386/kernel/pci-pc.c	Fri Nov  9 14:58:02 2001
+++ ha/arch/i386/kernel/pci-pc.c	Thu Dec 13 13:03:13 2001
@@ -12,6 +12,8 @@
 #include <linux/init.h>
 #include <linux/ioport.h>
 
+#include <asm/pci-bridge.h>
+
 #include <asm/segment.h>
 #include <asm/io.h>
 
@@ -23,6 +25,11 @@
 struct pci_bus *pci_root_bus = NULL;
 struct pci_ops *pci_root_ops = NULL;
 
+#ifdef CONFIG_CPCI_HOTSWAP
+extern struct list_head pci_root_buses;
+extern struct pci_controller* hose_head;
+#endif /* CONFIG_CPCI_HOTSWAP */
+
 int (*pci_config_read)(int seg, int bus, int dev, int fn, int reg, int len, u32 *value) = NULL;
 int (*pci_config_write)(int seg, int bus, int dev, int fn, int reg, int len, u32 value) = NULL;
 
@@ -1196,6 +1203,10 @@
 		return;
 	}
 
+#ifdef CONFIG_CPCI_HOTSWAP
+	CpciFindBridges();
+#endif /* CONFIG_CPCI_HOTSWAP */
+
 	printk("PCI: Probing PCI hardware\n");
 	pci_root_bus = pci_scan_bus(0, pci_root_ops, NULL);
 
@@ -1271,3 +1282,82 @@
 	pcibios_enable_irq(dev);
 	return 0;
 }
+
+#ifdef CONFIG_CPCI_HOTSWAP
+struct pci_controller*
+pci_bus_to_hose(int bus)
+{
+	struct pci_controller* hose = hose_head;
+
+	for (; hose; hose = hose->next)
+		if (bus >= hose->first_busno && bus <= hose->last_busno)
+			return hose;
+	return NULL;
+}
+
+/*
+ *  * Null PCI config access functions, for the case when we can't
+ *   * find a hose.
+ *    */
+#define NULL_PCI_OP(rw, size, type)                                     \
+static int                                                              \
+null_##rw##_config_##size(struct pci_dev *dev, int offset, type val)    \
+{                                                                       \
+        return PCIBIOS_DEVICE_NOT_FOUND;                                \
+}
+
+NULL_PCI_OP(read, byte, u8 *)
+NULL_PCI_OP(read, word, u16 *)
+NULL_PCI_OP(read, dword, u32 *)
+NULL_PCI_OP(write, byte, u8)
+NULL_PCI_OP(write, word, u16)
+NULL_PCI_OP(write, dword, u32)
+
+static struct pci_ops null_pci_ops =
+{
+	null_read_config_byte,
+	null_read_config_word,
+	null_read_config_dword,
+	null_write_config_byte,
+	null_write_config_word,
+	null_write_config_dword
+};
+
+/*
+ * These functions are used early on before PCI scanning is done
+ * and all of the pci_dev and pci_bus structures have been created.
+ */
+static struct pci_dev *
+fake_pci_dev(struct pci_controller *hose, int busnr, int devfn)
+{
+	static struct pci_dev dev;
+	static struct pci_bus bus;
+
+	if (hose == 0) {
+		hose = pci_bus_to_hose(busnr);
+		if (hose == 0)
+			printk(KERN_ERR "Can't find hose for PCI bus %d!\n", busnr);
+	}
+	dev.bus = &bus;
+	dev.sysdata = hose;
+	dev.devfn = devfn;
+	bus.number = busnr;
+	bus.ops = hose? hose->ops: &null_pci_ops;
+	return &dev;
+}
+
+#define EARLY_PCI_OP(rw, size, type)                                    \
+int early_##rw##_config_##size(struct pci_controller *hose, int bus,    \
+                               int devfn, int offset, type value)       \
+{                                                                       \
+        return pci_##rw##_config_##size(fake_pci_dev(hose, bus, devfn), \
+                                        offset, value);                 \
+}
+
+EARLY_PCI_OP(read, byte, u8 *)
+EARLY_PCI_OP(read, word, u16 *)
+EARLY_PCI_OP(read, dword, u32 *)
+EARLY_PCI_OP(write, byte, u8)
+EARLY_PCI_OP(write, word, u16)
+EARLY_PCI_OP(write, dword, u32)
+#endif /* CONFIG_CPCI_HOTSWAP */
diff -u -r --new-file linux/drivers/Makefile ha/drivers/Makefile
--- linux/drivers/Makefile	Sun Nov 11 11:09:32 2001
+++ ha/drivers/Makefile	Thu Dec 13 13:06:49 2001
@@ -47,4 +47,7 @@
 
 subdir-$(CONFIG_BLUEZ)		+= bluetooth
 
+subdir-$(CONFIG_CPCI_HOTSWAP)	+= ha
+subdir-$(CONFIG_EVENT_BROKER)	+= ha/event
+
 include $(TOPDIR)/Rules.make
diff -u -r --new-file linux/drivers/ha/Config.in ha/drivers/ha/Config.in
--- linux/drivers/ha/Config.in	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/Config.in	Thu Dec 13 13:07:07 2001
@@ -0,0 +1,21 @@
+#
+# Compact PCI chassis support code and drivers
+#
+bool 'Compact PCI Bus Hot Swap Support' CONFIG_CPCI_HOTSWAP
+
+if [ "$CONFIG_CPCI_HOTSWAP" = "y" ]; then
+   define_bool CONFIG_EVENT_BROKER y
+
+   choice '  Host and Compact PCI Chassis Type' \
+	 "   Motorola-MCP750-CPV5350 CONFIG_MOT_GEN \
+	     Ziatech-ZT5550 CONFIG_ZT_5550"
+
+   if [ "$CONFIG_MOT_GEN" = "y" ]; then
+      source drivers/ha/cpci/Config.mot82XX.in
+      source drivers/ha/cpci/Config.mot_nonha.in
+   fi
+
+   if [ "$CONFIG_ZT_5550" = "y" ]; then
+      source drivers/ha/cpci/Config.zia5083.in
+   fi
+fi
diff -u -r --new-file linux/drivers/ha/Makefile ha/drivers/ha/Makefile
--- linux/drivers/ha/Makefile	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/Makefile	Thu Dec 13 13:07:15 2001
@@ -0,0 +1,18 @@
+#
+# Makefile for the Linux kernel device drivers.
+#
+# 15 Sep 2000, Christoph Hellwig <hch@caldera.de>
+# Rewritten to use lists instead of if-statements.
+#
+
+
+mod-subdirs :=	
+
+subdir-y :=
+subdir-m :=
+
+
+subdir-$(CONFIG_CPCI_HOTSWAP)		+= cpci
+
+include $(TOPDIR)/Rules.make
+
Binary files linux/drivers/ha/cpci/.mot82XXhsc.c.swp and ha/drivers/ha/cpci/.mot82XXhsc.c.swp differ
diff -u -r --new-file linux/drivers/ha/cpci/Config.mot82XX.in ha/drivers/ha/cpci/Config.mot82XX.in
--- linux/drivers/ha/cpci/Config.mot82XX.in	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/Config.mot82XX.in	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,70 @@
+#
+# Compact PCI chassis support code and drivers
+#
+if [ "$CONFIG_PPC" = "y" ]; then
+   comment ''
+   comment 'Compact PCI IO Sizes for 82XX chassis (4K boundries required)'
+   int 'Slot  1' CONFIG_MOT_82XX_SLOT1_IO_SIZE 16
+   int 'Slot  2' CONFIG_MOT_82XX_SLOT2_IO_SIZE 16
+   int 'Slot  3' CONFIG_MOT_82XX_SLOT3_IO_SIZE 16
+   int 'Slot  4' CONFIG_MOT_82XX_SLOT4_IO_SIZE 16
+   int 'Slot  5' CONFIG_MOT_82XX_SLOT5_IO_SIZE 16
+   int 'Slot  6' CONFIG_MOT_82XX_SLOT6_IO_SIZE 16
+
+   int 'Slot 11' CONFIG_MOT_82XX_SLOT11_IO_SIZE 16
+   int 'Slot 12' CONFIG_MOT_82XX_SLOT12_IO_SIZE 16
+   int 'Slot 13' CONFIG_MOT_82XX_SLOT13_IO_SIZE 16
+   int 'Slot 14' CONFIG_MOT_82XX_SLOT14_IO_SIZE 16
+   int 'Slot 15' CONFIG_MOT_82XX_SLOT15_IO_SIZE 16
+   int 'Slot 16' CONFIG_MOT_82XX_SLOT16_IO_SIZE 16
+
+   comment ''
+   comment 'Compact PCI Memory Sizes for 82XX chassis (1M boundries required)'
+   int 'Slot  1' CONFIG_MOT_82XX_SLOT1_MEM_SIZE 64
+   int 'Slot  2' CONFIG_MOT_82XX_SLOT2_MEM_SIZE 64
+   int 'Slot  3' CONFIG_MOT_82XX_SLOT3_MEM_SIZE 64
+   int 'Slot  4' CONFIG_MOT_82XX_SLOT4_MEM_SIZE 64
+   int 'Slot  5' CONFIG_MOT_82XX_SLOT5_MEM_SIZE 64
+   int 'Slot  6' CONFIG_MOT_82XX_SLOT6_MEM_SIZE 64
+
+   int 'Slot 11' CONFIG_MOT_82XX_SLOT11_MEM_SIZE 64
+   int 'Slot 12' CONFIG_MOT_82XX_SLOT12_MEM_SIZE 64
+   int 'Slot 13' CONFIG_MOT_82XX_SLOT13_MEM_SIZE 64
+   int 'Slot 14' CONFIG_MOT_82XX_SLOT14_MEM_SIZE 64
+   int 'Slot 15' CONFIG_MOT_82XX_SLOT15_MEM_SIZE 64
+   int 'Slot 16' CONFIG_MOT_82XX_SLOT16_MEM_SIZE 64
+fi
+
+if [ "$CONFIG_X86" = "y" ]; then
+   comment ''
+   comment 'Compact PCI IO Sizes for 82XX chassis (4K boundries required)'
+   int 'Slot  1' CONFIG_MOT_82XX_SLOT1_IO_SIZE 4
+   int 'Slot  2' CONFIG_MOT_82XX_SLOT2_IO_SIZE 4
+   int 'Slot  3' CONFIG_MOT_82XX_SLOT3_IO_SIZE 4
+   int 'Slot  4' CONFIG_MOT_82XX_SLOT4_IO_SIZE 4
+   int 'Slot  5' CONFIG_MOT_82XX_SLOT5_IO_SIZE 4
+   int 'Slot  6' CONFIG_MOT_82XX_SLOT6_IO_SIZE 4
+
+   int 'Slot 11' CONFIG_MOT_82XX_SLOT11_IO_SIZE 4
+   int 'Slot 12' CONFIG_MOT_82XX_SLOT12_IO_SIZE 4
+   int 'Slot 13' CONFIG_MOT_82XX_SLOT13_IO_SIZE 4
+   int 'Slot 14' CONFIG_MOT_82XX_SLOT14_IO_SIZE 4
+   int 'Slot 15' CONFIG_MOT_82XX_SLOT15_IO_SIZE 4
+   int 'Slot 16' CONFIG_MOT_82XX_SLOT16_IO_SIZE 4
+
+   comment ''
+   comment 'Compact PCI Memory Sizes for 82XX chassis (1M boundries required)'
+   int 'Slot  1' CONFIG_MOT_82XX_SLOT1_MEM_SIZE 64
+   int 'Slot  2' CONFIG_MOT_82XX_SLOT2_MEM_SIZE 64
+   int 'Slot  3' CONFIG_MOT_82XX_SLOT3_MEM_SIZE 64
+   int 'Slot  4' CONFIG_MOT_82XX_SLOT4_MEM_SIZE 64
+   int 'Slot  5' CONFIG_MOT_82XX_SLOT5_MEM_SIZE 64
+   int 'Slot  6' CONFIG_MOT_82XX_SLOT6_MEM_SIZE 64
+
+   int 'Slot 11' CONFIG_MOT_82XX_SLOT11_MEM_SIZE 64
+   int 'Slot 12' CONFIG_MOT_82XX_SLOT12_MEM_SIZE 64
+   int 'Slot 13' CONFIG_MOT_82XX_SLOT13_MEM_SIZE 64
+   int 'Slot 14' CONFIG_MOT_82XX_SLOT14_MEM_SIZE 64
+   int 'Slot 15' CONFIG_MOT_82XX_SLOT15_MEM_SIZE 64
+   int 'Slot 16' CONFIG_MOT_82XX_SLOT16_MEM_SIZE 64
+fi
diff -u -r --new-file linux/drivers/ha/cpci/Config.mot_nonha.in ha/drivers/ha/cpci/Config.mot_nonha.in
--- linux/drivers/ha/cpci/Config.mot_nonha.in	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/Config.mot_nonha.in	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,46 @@
+#
+# Compact PCI chassis support code and drivers
+#
+if [ "$CONFIG_PPC" = "y" ]; then
+   comment ''
+   comment 'Compact PCI IO Sizes for Generic Hot Swap chassis (4K boundries required)'
+   hex 'Slot 1' CONFIG_MOT_GEN_SLOT1_IO_SIZE 16
+   hex 'Slot 2' CONFIG_MOT_GEN_SLOT2_IO_SIZE 16
+   hex 'Slot 3' CONFIG_MOT_GEN_SLOT3_IO_SIZE 16
+   hex 'Slot 4' CONFIG_MOT_GEN_SLOT4_IO_SIZE 16
+   hex 'Slot 5' CONFIG_MOT_GEN_SLOT5_IO_SIZE 16
+   hex 'Slot 6' CONFIG_MOT_GEN_SLOT6_IO_SIZE 16
+   hex 'Slot 7' CONFIG_MOT_GEN_SLOT7_IO_SIZE 16
+
+   comment ''
+   comment 'Compact PCI Memory Sizes for Generic Hot Swap chassis (1M boundries required)'
+   hex 'Slot 1' CONFIG_MOT_GEN_SLOT1_MEM_SIZE 64
+   hex 'Slot 2' CONFIG_MOT_GEN_SLOT2_MEM_SIZE 64
+   hex 'Slot 3' CONFIG_MOT_GEN_SLOT3_MEM_SIZE 64
+   hex 'Slot 4' CONFIG_MOT_GEN_SLOT4_MEM_SIZE 64
+   hex 'Slot 5' CONFIG_MOT_GEN_SLOT5_MEM_SIZE 64
+   hex 'Slot 6' CONFIG_MOT_GEN_SLOT6_MEM_SIZE 64
+   hex 'Slot 7' CONFIG_MOT_GEN_SLOT7_MEM_SIZE 64
+fi
+
+if [ "$CONFIG_X86" = "y" ]; then
+   comment ''
+   comment 'Compact PCI IO Sizes for Generic Hot Swap chassis (4K boundries required)'
+   hex 'Slot 1' CONFIG_MOT_GEN_SLOT1_IO_SIZE 8
+   hex 'Slot 2' CONFIG_MOT_GEN_SLOT2_IO_SIZE 8
+   hex 'Slot 3' CONFIG_MOT_GEN_SLOT3_IO_SIZE 8
+   hex 'Slot 4' CONFIG_MOT_GEN_SLOT4_IO_SIZE 8
+   hex 'Slot 5' CONFIG_MOT_GEN_SLOT5_IO_SIZE 8
+   hex 'Slot 6' CONFIG_MOT_GEN_SLOT6_IO_SIZE 8
+   hex 'Slot 7' CONFIG_MOT_GEN_SLOT7_IO_SIZE 4
+
+   comment ''
+   comment 'Compact PCI Memory Sizes for Generic Hot Swap chassis (1M boundries required)'
+   hex 'Slot 1' CONFIG_MOT_GEN_SLOT1_MEM_SIZE 64
+   hex 'Slot 2' CONFIG_MOT_GEN_SLOT2_MEM_SIZE 64
+   hex 'Slot 3' CONFIG_MOT_GEN_SLOT3_MEM_SIZE 64
+   hex 'Slot 4' CONFIG_MOT_GEN_SLOT4_MEM_SIZE 64
+   hex 'Slot 5' CONFIG_MOT_GEN_SLOT5_MEM_SIZE 64
+   hex 'Slot 6' CONFIG_MOT_GEN_SLOT6_MEM_SIZE 64
+   hex 'Slot 7' CONFIG_MOT_GEN_SLOT7_MEM_SIZE 64
+fi
diff -u -r --new-file linux/drivers/ha/cpci/Config.zia5083.in ha/drivers/ha/cpci/Config.zia5083.in
--- linux/drivers/ha/cpci/Config.zia5083.in	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/Config.zia5083.in	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,34 @@
+#
+# Compact PCI chassis support code and drivers
+#
+comment ''
+comment 'Compact PCI IO Sizes for 5083 chassis (4K boundries required)'
+int 'Slot  1' CONFIG_ZIA_5083_SLOT1_IO_SIZE 4
+int 'Slot  2' CONFIG_ZIA_5083_SLOT2_IO_SIZE 4
+int 'Slot  3' CONFIG_ZIA_5083_SLOT3_IO_SIZE 4
+int 'Slot  4' CONFIG_ZIA_5083_SLOT4_IO_SIZE 4
+int 'Slot  5' CONFIG_ZIA_5083_SLOT5_IO_SIZE 4
+int 'Slot  6' CONFIG_ZIA_5083_SLOT6_IO_SIZE 4
+
+int 'Slot 11' CONFIG_ZIA_5083_SLOT11_IO_SIZE 4
+int 'Slot 12' CONFIG_ZIA_5083_SLOT12_IO_SIZE 4
+int 'Slot 13' CONFIG_ZIA_5083_SLOT13_IO_SIZE 4
+int 'Slot 14' CONFIG_ZIA_5083_SLOT14_IO_SIZE 4
+int 'Slot 15' CONFIG_ZIA_5083_SLOT15_IO_SIZE 4
+int 'Slot 16' CONFIG_ZIA_5083_SLOT16_IO_SIZE 4
+
+comment ''
+comment 'Compact PCI Memory Sizes for 5083 chassis (1M boundries required)'
+int 'Slot  1' CONFIG_ZIA_5083_SLOT1_MEM_SIZE 64
+int 'Slot  2' CONFIG_ZIA_5083_SLOT2_MEM_SIZE 64
+int 'Slot  3' CONFIG_ZIA_5083_SLOT3_MEM_SIZE 64
+int 'Slot  4' CONFIG_ZIA_5083_SLOT4_MEM_SIZE 64
+int 'Slot  5' CONFIG_ZIA_5083_SLOT5_MEM_SIZE 64
+int 'Slot  6' CONFIG_ZIA_5083_SLOT6_MEM_SIZE 64
+
+int 'Slot 11' CONFIG_ZIA_5083_SLOT11_MEM_SIZE 64
+int 'Slot 12' CONFIG_ZIA_5083_SLOT12_MEM_SIZE 64
+int 'Slot 13' CONFIG_ZIA_5083_SLOT13_MEM_SIZE 64
+int 'Slot 14' CONFIG_ZIA_5083_SLOT14_MEM_SIZE 64
+int 'Slot 15' CONFIG_ZIA_5083_SLOT15_MEM_SIZE 64
+int 'Slot 16' CONFIG_ZIA_5083_SLOT16_MEM_SIZE 64
diff -u -r --new-file linux/drivers/ha/cpci/Makefile ha/drivers/ha/cpci/Makefile
--- linux/drivers/ha/cpci/Makefile	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/Makefile	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,19 @@
+#
+# Makefile for the Compact PCI Chassis support drivers.
+#
+
+O_TARGET	:= cpci.o
+
+obj-y   := cpci_core.o cpci_enum.o cpci_debug.o piphs.o
+obj-m   :=
+obj-n   :=
+obj-    :=
+
+export-objs := cpci_core.o
+
+obj-$(CONFIG_MOT_GEN)		+= mot82XXhsc.o mot_enum.o mot_cpci.o
+obj-$(CONFIG_ZT_5550)		+= pdphs_zt5550.o zia5083cpci.o
+
+
+include $(TOPDIR)/Rules.make
+
diff -u -r --new-file linux/drivers/ha/cpci/cpci_core.c ha/drivers/ha/cpci/cpci_core.c
--- linux/drivers/ha/cpci/cpci_core.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/cpci_core.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,1220 @@
+/*
+ * cpci_core.c
+ *
+ * Core control routines for cPCI control.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ *
+ */
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/cpci.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/pci.h>
+#include <linux/pci_auto.h>
+#include <linux/netdevice.h>
+#include <linux/event.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#include "cpci_core.h"
+#include "phs.h"
+
+#define MODVERSIONS
+
+/* Prototypes for internal functionality. */
+int  CpciAddBus(int);
+int  CpciDelBus(int, int);
+int  CpciAddSlot(int);
+int  CpciDelSlot(int);
+int  CpciFillInSlotInfo(CpciIoctlSlotInfo *);
+void CpciHandleNextEnum(void *);
+int  CpciGetAsnycReq(unsigned long);
+int  CpciSendAsyncResult(unsigned long);
+void CpciFindDriver(struct pci_dev *);
+char *CpciGetName(struct pci_dev *);
+
+void CpciSendAddSlotFail(int, int, int);
+
+/* Prototypes for device dependant init functions. */
+#ifdef CONFIG_MOT_GEN
+void motCpci_init(void);
+void motCpci_find_bridges(void);
+#endif
+#ifdef CONFIG_MOT_GENERIC
+void motGenCpci_init(void);
+void motGenCpci_find_bridges(void);
+#endif
+#ifdef CONFIG_ZT_5550
+void zia5083cpci_init(void);
+void zia5083cpci_find_bridges(void);
+#endif
+
+/* Linux Driver prototypes. */
+static int cpci_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+static int cpci_open(struct inode *, struct file *);
+static int cpci_release(struct inode *, struct file *);
+
+typedef struct _CpciOpenDevQ {
+	struct pci_dev *Dev;
+	struct _CpciOpenDevQ *Next;
+} CpciOpenDevQ;
+
+static struct  file_operations cpci_fops = {
+	ioctl:	  cpci_ioctl,
+	open:	  cpci_open,
+	release:  cpci_release,
+};
+
+/* Data structure declaration. */
+int	 CpciMajor;
+CpciFunc *CpciFunctions;
+CpciNodeInfo *CpciBuses;
+CpciNodeInfo *CpciSlots;
+CpciInfo *CpciInfos;
+
+int CpciEventId;
+int CpciHsiEventClass;
+
+int CpciOpenCount;
+CpciOpenDevQ *CpciOpenDevHead = NULL;
+
+wait_queue_head_t CpciHandleEnumWaitQ;
+struct timer_list CpciHandleEnumTimeOut;
+void CpciHandleEnumTimeOutFunc(unsigned long);
+
+spinlock_t CpciPciAccessLock = SPIN_LOCK_UNLOCKED;
+
+extern struct list_head pci_drivers;
+
+/*
+ * Init function.  Called after first setup of pci bus.
+ */
+int
+cpci_init(void)
+{
+	if ((CpciMajor = register_chrdev(0, "cPCI", &cpci_fops)) < 0) {
+		printk("Cound not register cPCI driver\n");
+		return -ENODEV;
+	}
+
+	/* Init controls for the HandleNextEnum timeout sequence. */
+	init_waitqueue_head(&CpciHandleEnumWaitQ);
+	init_timer(&CpciHandleEnumTimeOut);
+	CpciHandleEnumTimeOut.function = CpciHandleEnumTimeOutFunc;
+
+	/* Register to send and receive events */
+	CpciEventId = EventRegisterId("cPCI");
+
+	/* Register an event class for the cPCI hot swap events */
+	EventRegisterEventClass("cPCI_Hsi", &CpciHsiEventClass);
+
+#ifdef CONFIG_MOT_GEN
+	motCpci_init();
+#endif
+#ifdef CONFIG_MOT_GENERIC
+	motGenCpci_init();
+#endif
+#ifdef CONFIG_ZT_5550
+	zia5083cpci_init();
+#endif
+	/* Register the enum callback with the PICMG 2.12 routines. */
+	SetEnumEventCallback(NULL, CpciHandleNextEnum, (void *)NULL);
+	EnableEnumEvents(NULL, TRUE);
+
+	return 0;
+}
+
+/*
+ * Linux driver ioctl functionality.
+ */
+static int
+cpci_ioctl(struct inode *inode,
+                struct file *file, unsigned int cmd, unsigned long arg)
+{
+	int RetVal;
+	CpciIoctlBusInfo BusInfoIoctl;
+	CpciIoctlSlotInfo SlotInfoIoctl;
+	unsigned long flags;
+	int Loop;
+	int LoopEnd;
+	int Offset;
+
+	switch (cmd) {
+	case CPCI_ADD_BUS:
+		spin_lock_irqsave(&CpciPciAccessLock, flags);
+		RetVal = CpciAddBus(arg - 1);
+		spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+
+		return RetVal;
+
+	case CPCI_DEL_BUS:
+		spin_lock_irqsave(&CpciPciAccessLock, flags);
+		RetVal = CpciDelBus(arg - 1, 1);
+		spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+
+		return RetVal;
+
+	case CPCI_ADD_SLOT:
+		spin_lock_irqsave(&CpciPciAccessLock, flags);
+		RetVal = CpciAddSlot(arg - 1);
+		spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+
+		return RetVal;
+
+	case CPCI_DEL_SLOT:
+		spin_lock_irqsave(&CpciPciAccessLock, flags);
+		RetVal = CpciDelSlot(arg - 1);
+		spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+
+		return RetVal;
+
+	case CPCI_GET_CHASSIS_TYPE:
+		if (copy_to_user((void *)arg,
+				&CpciInfos->ChassisType, sizeof(int))) {
+			return -EFAULT;
+		}
+
+		return 0;
+
+	case CPCI_GET_BUS_INFO:
+		if (copy_from_user((void *)&BusInfoIoctl,
+				(void *)arg, sizeof(CpciIoctlBusInfo))) {
+			return -EFAULT;
+		}
+
+		BusInfoIoctl.StartSlot = CpciInfos->StartSlotNum[BusInfoIoctl.Bus];
+		BusInfoIoctl.EndSlot = CpciInfos->EndSlotNum[BusInfoIoctl.Bus];
+
+		LoopEnd = BusInfoIoctl.EndSlot - BusInfoIoctl.StartSlot + 1;
+		Offset = BusInfoIoctl.StartSlot;
+		for (Loop = 0; Loop < LoopEnd; Loop ++) {
+			BusInfoIoctl.Allocated[Loop] =
+					CpciSlots[Loop + Offset].Allocated;
+		}
+
+		if (copy_to_user((void *)arg,
+				&BusInfoIoctl, sizeof(CpciIoctlBusInfo))) {
+			return -EFAULT;
+		}
+
+		return 0;
+
+	case CPCI_GET_SLOT_INFO:
+		if (copy_from_user((void *)&SlotInfoIoctl,
+				(void *)arg, sizeof(CpciIoctlSlotInfo))) {
+			return -EFAULT;
+		}
+
+		if ((RetVal = CpciFillInSlotInfo(&SlotInfoIoctl)) < 0) {
+			return RetVal;
+		}
+
+		if (copy_to_user((void *)arg,
+				&SlotInfoIoctl, sizeof(CpciIoctlSlotInfo))) {
+			return -EFAULT;
+		}
+
+		return 0;
+
+	default:
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Linux driver open functionality.
+ */
+static int
+cpci_open(struct inode *inode, struct file *file)
+{
+	CpciOpenDevQ *DelDev;
+
+	CpciOpenCount++;
+
+	while (CpciOpenDevHead) {
+		if (!(CpciOpenDevHead->Dev->driver)) {
+			EventSendEvent(CpciEventId, 0,
+				CpciHsiEventClass, CPCI_EVENT_INSERT,
+				CpciOpenDevHead->Dev->vendor,
+				CpciOpenDevHead->Dev->device,
+				CpciOpenDevHead->Dev->subsystem_vendor,
+				CpciOpenDevHead->Dev->subsystem_device,
+				0, NULL);
+		}
+
+		DelDev = CpciOpenDevHead;
+		CpciOpenDevHead = CpciOpenDevHead->Next;
+		kfree(DelDev);
+	}
+
+	return 0;
+}
+
+void
+CpciRegisterOpenCheck(struct pci_dev *dev)
+{
+	CpciOpenDevQ *TmpDev = CpciOpenDevHead;
+
+	if (CpciOpenDevHead == NULL) {
+		CpciOpenDevHead = kmalloc(sizeof(CpciOpenDevQ), GFP_KERNEL);
+		CpciOpenDevHead->Dev = dev; 
+		CpciOpenDevHead->Next = NULL;
+		return;
+	}
+
+	while (TmpDev->Next) {
+		TmpDev = TmpDev->Next;
+	}
+
+	TmpDev->Next = kmalloc(sizeof(CpciOpenDevQ), GFP_KERNEL);
+	TmpDev->Next->Dev = dev; 
+	TmpDev->Next->Next = NULL;
+	return;
+}
+
+/*
+ * Linux driver close functionality.
+ */
+static int
+cpci_release(struct inode *inode, struct file *file)
+{
+	CpciOpenCount -= 1;
+
+	return 0;
+}
+
+void
+CpciFindBridges(void)
+{
+#ifdef CONFIG_MOT_GEN
+	motCpci_find_bridges();
+#endif
+#ifdef CONFIG_MOT_GENERIC
+	motGenCpci_find_bridges();
+#endif
+#ifdef CONFIG_ZT_5550
+	zia5083cpci_find_bridges();
+#endif
+}
+
+/*
+ * Basis for the add bus ioctl functionality.  This function
+ * first checks to see if the bus is already mapped in.  If not
+ * it calls the device dependent allocate and init function to
+ * physically attach the bus and the device independant function
+ * to setup the kernel data structures.
+ */
+int
+CpciAddBus(int bus)
+{
+	/* If this is a standard hot swap chassis with no
+	 * bus control this function is not supported.  The
+	 * individual processor - chassis startup code is
+	 * responsible to setting the AllocAndInitBus function
+	 * pointer to NULL to indicate this.
+	 */
+	if (CpciFunctions->AllocAndInitBus == NULL) {
+		return -EINVAL;
+	}
+
+	if ((bus < 0) || (bus > CpciInfos->MaxBusNum)) {
+		return -EINVAL;
+	}
+
+	if (CpciBuses[bus].Allocated) {
+		return -EBUSY;
+	}
+
+
+	EnableEnumEvents(NULL, FALSE);
+	CpciFunctions->AllocAndInitBus(bus);
+	CpciSetupBus(bus);
+	EnableEnumEvents(NULL, TRUE);
+
+	return 0;
+}
+
+/*
+ * Basis for the delete bus ioctl.  After chicking to ensure this
+ * is a correct bus to remove, the kernel data structures are reset
+ * and deallocated and then a device dependant function is called to
+ * physically remove the bus from the host processor.
+ */
+int
+CpciDelBus(int bus, int detach)
+{
+	int Slot;
+	struct pci_dev *Dev;
+
+	/* If this is a standard hot swap chassis with no
+	 * bus control this function is not supported.  The
+	 * individual processor - chassis startup code is
+	 * responsible to setting the AllocAndInitBus function
+	 * pointer to NULL to indicate this.
+	 */
+	if (CpciFunctions->DeallocAndShutdownBus == NULL) {
+		return -EINVAL;
+	}
+
+	if ((bus < 0) || (bus > CpciInfos->MaxBusNum)) {
+		return -EINVAL;
+	}
+
+	if (!CpciBuses[bus].Allocated) {
+		return -ENODEV;
+	}
+
+	for (Slot = CpciInfos->StartSlotNum[bus];
+			Slot <= CpciInfos->EndSlotNum[bus]; Slot++) {
+		CpciDelSlot(Slot);
+	}
+
+	Dev = pci_find_slot(0, CpciBuses[bus].DevFn);
+
+#ifdef CONFIG_PROC_FS
+	pci_proc_detach_device(Dev);
+#endif
+	list_del(&Dev->bus_list);
+	list_del(&Dev->global_list);
+	CpciFreeResources(Dev);
+	kfree(Dev);
+
+	CpciBuses[bus].Allocated = 0;
+
+	if (detach) {
+		CpciFunctions->DeallocAndShutdownBus(bus);
+	}
+
+	return 0;
+}
+
+/*
+ * This function is the basis for the add slot ioctl and provides the
+ * slot mapping functionality for the add buss ioctl.  The slot number
+ * is first checked to decide which bus it is on.  After that
+ * the hardware is configured and then the operating system data structurs
+ * are allocated and filled in.
+ */
+int
+CpciAddSlot(int slot)
+{
+	int Bus;
+	struct pci_dev *Dev;
+	struct pci_dev TempDev;
+	struct pci_dev *CpciDev;
+	struct pci_bus *CpciBus;
+	struct pci_bus *SlotBus;
+	unsigned char HdrType;
+	int SlotSubDev = 0;
+	int Type;
+
+	if ((slot >= CpciInfos->StartSlotNum[0]) &&
+					(slot <= CpciInfos->EndSlotNum[0])) {
+		Bus = 0;
+	} else if ((slot >= CpciInfos->StartSlotNum[1]) &&
+					(slot <= CpciInfos->EndSlotNum[1])) {
+		Bus = 1;
+	} else {
+		return -EINVAL;
+	}
+
+	if (CpciSlots[slot].Allocated == CPCI_SLOT_ALLOCATED) {
+		EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_INS_FAIL,
+					slot, CPCI_BI_FAIL_BUSY, 0, 0, 0, NULL);
+		return -EBUSY;
+	}
+
+	/* Can have a dangling condition so reset it first. */
+	if ((CpciSlots[slot].Allocated & 0xff) == CPCI_SLOT_INSFAILED) {
+		CpciSlots[slot].Allocated = CPCI_SLOT_FREE;
+	}
+
+	/* Standard hot swap chassis do not support this. */
+	if ((CpciFunctions->CheckHealthy != NULL) &&
+	    !CpciFunctions->CheckHealthy(slot)) {
+		EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_INS_FAIL,
+					slot, CPCI_BI_FAIL_HEALTH, 0, 0, 0, NULL);
+		return -ENODEV;
+	}
+
+	if ((Type = CpciConfigSlot(slot, CpciSlots[slot].Hose,
+					CpciBuses[Bus].FirstBusNo)) < 0) {
+		CpciSendAddSlotFail(slot, Bus, CPCI_BI_FAIL_CONFIG);
+		return Type;
+	}
+
+	if (!(CpciDev = pci_find_slot(0, CpciBuses[Bus].DevFn))) {
+		CpciSendAddSlotFail(slot, Bus, CPCI_BI_FAIL_NODEV);
+		return -ENODEV;
+	}
+
+	if (!(CpciBus = CpciDev->subordinate)) {
+		CpciSendAddSlotFail(slot, Bus, CPCI_BI_FAIL_NOSUB);
+		return -ENODEV;
+	}
+
+	CpciSlots[slot].UseCount = 0;
+
+	/* scan this sub bus */
+	memset(&TempDev, 0, sizeof(TempDev));
+	TempDev.bus = CpciBus;
+	TempDev.sysdata = CpciSlots[slot].Hose;
+	TempDev.devfn = CpciSlots[slot].DevFn;
+
+	pci_read_config_byte(&TempDev, PCI_HEADER_TYPE, &HdrType);
+	TempDev.hdr_type = HdrType & 0x7f;
+
+	/* If this is just a device being inserted then don't scan it. */
+	if (Type == PCI_HEADER_TYPE_NORMAL) {
+		if (!(Dev = pci_scan_slot(&TempDev))) {
+			CpciSendAddSlotFail(slot, Bus, CPCI_BI_FAIL_SCAN);
+			return -ENODEV;
+		}
+#ifdef CONFIG_PROC_FS
+		pci_proc_attach_device(Dev);
+#endif
+		CpciFunctions->MapIrq(Dev);
+
+		Dev->cpci_location = (slot << 16) | SlotSubDev++;
+
+		EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_INS_SUCC,
+					slot, 0, 0, 0, 0, NULL);
+
+		CpciFindDriver(Dev);
+		return 0;
+	}
+
+	if (!(Dev = pci_scan_device(&TempDev))) {
+		CpciSendAddSlotFail(slot, Bus, CPCI_BI_FAIL_SCAN);
+		return -ENODEV;
+	}
+
+	pci_name_device(Dev);
+
+	list_add_tail(&Dev->global_list, &pci_devices);
+	list_add_tail(&Dev->bus_list, &CpciBus->devices);
+#ifdef CONFIG_PROC_FS
+	pci_proc_attach_device(Dev);
+#endif
+
+	SlotBus = pci_add_new_bus(CpciBus, Dev, CpciSlots[slot].FirstBusNo);
+
+	pci_do_scan_bus(SlotBus);
+
+	SlotBus->subordinate = CpciSlots[slot].LastBusNo;
+	pci_read_bridge_bases(SlotBus);
+
+	if (SlotBus->resource[1]->start && (SlotBus->resource[1]->end != -1)) {
+		SlotBus->resource[1]->start += CpciSlots[slot].Hose->pci_mem_offset;
+		SlotBus->resource[1]->end += CpciSlots[slot].Hose->pci_mem_offset;
+	}
+
+	EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_INS_SUCC,
+					slot, 0, 0, 0, 0, NULL);
+
+	pci_for_each_dev(Dev) {
+		if ((Dev->bus->number >= SlotBus->number) &&
+		    (Dev->bus->number <= SlotBus->subordinate)) {
+			CpciFunctions->MapIrq(Dev);
+#ifdef CONFIG_PROC_FS
+			pci_proc_attach_device(Dev);
+#endif
+			/* If this is bridge then do not look for a driver. */
+			if ((Dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+				continue;
+			}
+
+			Dev->cpci_location = (slot << 16) | SlotSubDev++;
+
+			CpciFindDriver(Dev);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Provide the remove slot ioctl functionality and other functionality used
+ * by the remove bus ioctl.
+ */
+int
+CpciDelSlot(int slot)
+{
+	int Bus;
+	struct pci_dev *Dev;
+	char *name;
+
+	if ((slot >= CpciInfos->StartSlotNum[0]) &&
+					(slot <= CpciInfos->EndSlotNum[0])) {
+		Bus = 0;
+	} else if ((slot >= CpciInfos->StartSlotNum[1]) &&
+					(slot <= CpciInfos->EndSlotNum[1])) {
+		Bus = 1;
+	} else {
+		return -EINVAL;
+	}
+
+	if (CpciSlots[slot].Allocated == CPCI_SLOT_FREE) {
+		EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_REM_FAIL,
+						slot, 0, 0, 0, 0, NULL);
+		return -ENODEV;
+	}
+
+	if ((CpciSlots[slot].Allocated & 0xff) == CPCI_SLOT_INSFAILED) {
+		CpciTurnBlueLedOn(slot);
+		CpciSlots[slot].Allocated = CPCI_SLOT_FREE;
+	}
+
+	CpciSlots[slot].UseCount |= CPCI_ENUM_EXTRACT;
+
+	pci_for_each_dev_reverse(Dev) {
+	    if ((Dev->bus->number >= CpciSlots[slot].FirstBusNo) &&
+	        (Dev->bus->number <= CpciSlots[slot].LastBusNo)) {
+		if (Dev->driver) {
+		    if (Dev->driver->remove) {
+
+			name = CpciGetName(Dev);
+
+			EventSendEvent(CpciEventId, 0,
+				CpciHsiEventClass, CPCI_EVENT_SHUTDOWN,
+				slot, Dev->cpci_location & 0xffff,
+				Dev->class >> 8, 0,
+				strlen(name) + 1, name);
+
+			Dev->driver->remove(Dev);
+			continue;
+		    }
+		}
+
+#ifdef CONFIG_PROC_FS
+		pci_proc_detach_device(Dev);
+#endif
+		list_del(&Dev->bus_list);
+		list_del(&Dev->global_list);
+		CpciFreeResources(Dev);
+		kfree(Dev);
+	    }
+
+	    if ((Dev->bus->number == CpciSlots[slot].Bus) &&
+	         (Dev->devfn == CpciSlots[slot].DevFn)) {
+		if (Dev->driver) {
+		    if (Dev->driver->remove) {
+
+			name = CpciGetName(Dev);
+
+			EventSendEvent(CpciEventId, 0,
+				CpciHsiEventClass, CPCI_EVENT_SHUTDOWN,
+				slot, Dev->cpci_location & 0xffff,
+				Dev->class >> 8, 0,
+				strlen(name) + 1, name);
+
+			Dev->driver->remove(Dev);
+		    }
+		}
+	    }
+	}
+
+	if ((CpciSlots[slot].Allocated == CPCI_SLOT_ALLOCATED) &&
+					((CpciSlots[slot].UseCount & 0xffff) == 0)) {
+		Dev = pci_find_slot(CpciBuses[Bus].FirstBusNo, CpciSlots[slot].DevFn);
+
+#ifdef CONFIG_PROC_FS
+		pci_proc_detach_device(Dev);
+#endif
+		list_del(&Dev->bus_list);
+		list_del(&Dev->global_list);
+		CpciFreeResources(Dev);
+		kfree(Dev);
+
+		CpciSlots[slot].Allocated = CPCI_SLOT_FREE;
+
+		EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_REM_SUCC,
+						slot, 0, 0, 0, 0, NULL);
+		CpciTurnBlueLedOn(slot);
+	}
+
+	return 0;
+}
+
+/*
+ * Configure a top level cPCI bridge based on device dependant values.
+ */
+int
+CpciConfigCpciBridge(struct pci_controller *hose, int bus, int devfn, int offset)
+{
+	unsigned Latency, CacheLine;
+	unsigned short SecondaryStatus;
+	unsigned int Upper;
+	struct pci_auto_addrs PciAddrs;
+	unsigned short BridgeControl;
+
+	PciAddrs.io_start = CpciBuses[offset].IoStart;
+	PciAddrs.io_end = CpciBuses[offset].IoEnd;
+	PciAddrs.mem_start = CpciBuses[offset].MemStart;
+	PciAddrs.mem_end = CpciBuses[offset].MemEnd;
+
+	pciauto_prescan_setup_bridge(hose, bus, devfn,
+				CpciBuses[offset].FirstBusNo, 
+				&PciAddrs);
+
+	PciAddrs.io_end = CpciBuses[offset].IoStart;
+	PciAddrs.mem_end = CpciBuses[offset].MemStart;
+
+	pciauto_postscan_setup_bridge(hose, bus, devfn,
+				CpciBuses[offset].LastBusNo,
+				&PciAddrs);
+
+	CacheLine = 0x8;
+	early_write_config_byte(hose, bus, devfn, PCI_CACHE_LINE_SIZE, CacheLine);
+
+	Latency = 0x80;
+	early_write_config_byte(hose, bus, devfn, PCI_LATENCY_TIMER, Latency);
+	early_write_config_byte(hose, bus, devfn, PCI_SEC_LATENCY_TIMER, Latency);
+
+	Upper = 0xffffffff;
+	early_write_config_dword(hose, bus, devfn, PCI_PREF_BASE_UPPER32, Upper);
+
+	SecondaryStatus = 0x2000;
+	early_write_config_word(hose, bus, devfn, PCI_SEC_STATUS, SecondaryStatus);
+
+	early_read_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, &BridgeControl);
+	BridgeControl &= ~PCI_BRIDGE_CTL_NO_ISA;
+	early_write_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, BridgeControl);
+
+	return 0;
+}
+
+/*
+ * Configure the bridge for a cPCI slot and then autoscan below it.
+ */
+int
+CpciConfigSlot(int slot, struct pci_controller *hose, int bus)
+{
+	int SubBus;
+	unsigned short Command;
+	unsigned char HeaderType;
+	unsigned int Latency, CacheLine;
+	unsigned short SecondaryStatus;
+	unsigned int Upper;
+	struct pci_auto_addrs PciAddrs;
+	int ProbeDevFn = CpciSlots[slot].DevFn;
+
+	PciAddrs.io_start = CpciSlots[slot].IoStart;
+	PciAddrs.io_end = CpciSlots[slot].IoEnd;
+	PciAddrs.mem_start = CpciSlots[slot].MemStart;
+	PciAddrs.mem_end = CpciSlots[slot].MemEnd;
+
+	early_read_config_byte(hose, bus, ProbeDevFn, PCI_HEADER_TYPE, &HeaderType);
+
+	/* If header is 0xff then the slot is considered to be not populated. */
+	if (HeaderType == 0xff)
+		return -ENOENT;
+ 
+	switch (HeaderType & 0x7f) {	/* Strip the multifunction bit off */
+	case PCI_HEADER_TYPE_NORMAL:
+		/* This code assumes an IDE controller will not be installed
+		 * for the moment.
+		 */
+		early_read_config_word(hose, bus, ProbeDevFn, PCI_COMMAND, &Command);
+		early_write_config_word(hose, bus, ProbeDevFn, PCI_COMMAND,
+					 Command & ~(PCI_COMMAND_IO |
+					             PCI_COMMAND_MEMORY |
+						     PCI_COMMAND_MASTER));
+		early_write_config_byte(hose, bus, ProbeDevFn, PCI_LATENCY_TIMER, 0x80);
+
+		/* Allocate PCI I/O and/or memory space */
+		if (pciauto_setup_bars(hose, bus, ProbeDevFn, &PciAddrs) << 0) {
+			return -ENOSPC;
+		}
+ 
+		early_read_config_word(hose, bus, ProbeDevFn, PCI_COMMAND, &Command);
+		early_write_config_word(hose, bus, ProbeDevFn, PCI_COMMAND,
+					 Command | PCI_COMMAND_IO |
+					           PCI_COMMAND_MEMORY |
+						   PCI_COMMAND_MASTER);
+		early_write_config_byte(hose, bus, ProbeDevFn, PCI_LATENCY_TIMER, 0x80);
+		/* Indicte the slot has been initialized */
+		CpciSlots[slot].Allocated = CPCI_SLOT_ALLOCATED;
+		return PCI_HEADER_TYPE_NORMAL;
+
+	case PCI_HEADER_TYPE_BRIDGE:
+		CacheLine = 0x8;
+		early_write_config_byte(hose, bus, ProbeDevFn, PCI_CACHE_LINE_SIZE, CacheLine);
+
+		Latency = 0x80;
+		early_write_config_byte(hose, bus, ProbeDevFn, PCI_LATENCY_TIMER, Latency);
+		early_write_config_byte(hose, bus, ProbeDevFn, PCI_SEC_LATENCY_TIMER, Latency);
+
+		Upper = 0xffffffff;
+		early_write_config_dword(hose, bus, ProbeDevFn, PCI_PREF_BASE_UPPER32, Upper);
+
+		SecondaryStatus = 0x2000;
+		early_write_config_word(hose, bus, ProbeDevFn, PCI_SEC_STATUS, SecondaryStatus);
+
+		pciauto_prescan_setup_bridge(hose, bus, ProbeDevFn,
+					CpciSlots[slot].FirstBusNo, 
+					&PciAddrs);
+
+		if ((SubBus = pciauto_bus_scan(hose, CpciSlots[slot].FirstBusNo,
+					&PciAddrs)) < 0) {
+			return -ENOSPC;
+		}
+
+		pciauto_postscan_setup_bridge(hose, bus, ProbeDevFn, SubBus, &PciAddrs);
+
+		CpciSlots[slot].Allocated = CPCI_SLOT_ALLOCATED;
+		return PCI_HEADER_TYPE_BRIDGE;
+
+	default:
+		printk("Slot %d has an unknown PCI header type %d\n", slot+1, HeaderType);
+		return -EINVAL;
+	}
+}
+
+/*
+ * Thus function is used by both the add bus ioctl and system startup
+ * code.  It confifure a cPCI bus and all the existing slots below it.
+ * The initialization includes pci bridges, devices and all the associated
+ * kernel data structures.
+ */
+void
+CpciSetupBus(int domain)
+{
+	int Slot;
+	struct pci_dev *Dev;
+	struct pci_dev TempDev;
+	struct pci_bus *HeadBus;
+	struct pci_bus *CpciBus;
+	unsigned char HdrType;
+	unsigned short Command;
+
+	CpciConfigCpciBridge(CpciBuses[domain].Hose, 0,
+			     CpciBuses[domain].DevFn, domain);
+	CpciBuses[domain].Allocated = 1;
+
+	/* Set up the kernel info for this bus. */
+	HeadBus = pci_bus_b(pci_root_buses.next);
+
+	memset(&TempDev, 0, sizeof(TempDev));
+	TempDev.bus = HeadBus;
+	TempDev.sysdata = CpciBuses[domain].Hose;
+	TempDev.devfn = CpciBuses[domain].DevFn;
+
+	pci_read_config_byte(&TempDev, PCI_HEADER_TYPE, &HdrType);
+	TempDev.hdr_type = HdrType & 0x7f;
+
+	Dev = pci_scan_device(&TempDev);
+	pci_name_device(Dev);
+
+	list_add_tail(&Dev->global_list, &pci_devices);
+	list_add_tail(&Dev->bus_list, &HeadBus->devices);
+#ifdef CONFIG_PROC_FS
+	pci_proc_attach_device(Dev);
+#endif
+
+	CpciBus = pci_add_new_bus(HeadBus, Dev, CpciBuses[domain].FirstBusNo);
+
+	pci_read_bridge_bases(CpciBus);
+
+	if (CpciBus->resource[1]->start && (CpciBus->resource[1]->end != -1)) {
+		CpciBus->resource[1]->start +=
+				CpciBuses[domain].Hose->pci_mem_offset;
+		CpciBus->resource[1]->end +=
+				CpciBuses[domain].Hose->pci_mem_offset;
+	}
+
+	CpciBus->subordinate = CpciBuses[domain].LastBusNo;
+
+	/* Sanitize the slots before starting to config them. */
+	for (Slot = CpciInfos->StartSlotNum[domain];
+				Slot <= CpciInfos->EndSlotNum[domain]; Slot++) {
+		struct pci_controller *Hose = CpciSlots[Slot].Hose;
+		int Bus = CpciBuses[domain].FirstBusNo;
+		int ProbeDevFn = CpciSlots[Slot].DevFn;
+
+		early_read_config_word(Hose, Bus, ProbeDevFn,
+				       PCI_COMMAND, &Command);
+		Command &= ~(PCI_COMMAND_IO |
+			     PCI_COMMAND_MEMORY |
+			     PCI_COMMAND_MASTER);
+		early_write_config_word(Hose, Bus, ProbeDevFn,
+					PCI_COMMAND, Command);
+
+		early_read_config_byte(Hose, Bus, ProbeDevFn,
+				       PCI_HEADER_TYPE, &HdrType);
+		if ((HdrType & 0x7f) == PCI_HEADER_TYPE_BRIDGE) {
+			early_write_config_byte(Hose, Bus, ProbeDevFn,
+						PCI_SECONDARY_BUS, 0);
+			early_write_config_byte(Hose, Bus, ProbeDevFn,
+						PCI_SUBORDINATE_BUS, 0);
+		}
+	}
+
+	for (Slot = CpciInfos->StartSlotNum[domain];
+				Slot <= CpciInfos->EndSlotNum[domain]; Slot++) {
+		CpciAddSlot(Slot);
+	}
+
+	/* Turn on enum processing. */
+	CpciFunctions->SetEnumMask(domain, CPCI_BIT_SET);
+
+	return;
+}
+
+/*
+ * Free the resource data structures allocated in a pci_dev struct.
+ */
+void
+CpciFreeResources(struct pci_dev *dev)
+{
+	int loop;
+
+	for (loop = 0; loop < PCI_NUM_RESOURCES; loop++) {
+		struct resource *res = dev->resource + loop;
+		if (res->parent)
+			release_resource(res);
+	}
+}
+
+void
+CpciHandleNextEnum(void *arg)
+{
+	int Bus, Slot;
+	int TimeOutCnt;
+	unsigned long flags;
+
+	/* Check for an extract enum first.  If one is found changes are
+	 * there are no others.  If there are the 2.12 code will trip on
+	 * an enum again and call this code anyways.
+	 */
+	for (TimeOutCnt = 0; TimeOutCnt < 5; TimeOutCnt++) {
+		for (Bus = 0; Bus < CpciInfos->MaxBusNum; Bus++) {
+			if (!CpciBuses[Bus].Allocated) {
+				continue;
+			}
+	
+			for (Slot = CpciInfos->StartSlotNum[Bus];
+					Slot <= CpciInfos->EndSlotNum[Bus]; Slot++) {
+				if (CpciSlots[Slot].Allocated == CPCI_SLOT_ALLOCATED) {
+					if (CpciEnumCheckAndClear(Slot, 1) == CPCI_ENUM_EXT) {
+						spin_lock_irqsave(&CpciPciAccessLock, flags);
+						CpciDelSlot(Slot);
+						spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+						return;
+					}
+				}
+			}
+		}
+
+		/* Start the timeout sequence going and sleep. */
+		CpciHandleEnumTimeOut.data = 1;
+		CpciHandleEnumTimeOut.expires = jiffies + HZ/30;
+		add_timer(&CpciHandleEnumTimeOut);
+
+		sleep_on(&CpciHandleEnumWaitQ);
+	}
+
+	/* Now handle any remaining events. */
+	for (Bus = 0; Bus < CpciInfos->MaxBusNum; Bus++) {
+		if (!CpciBuses[Bus].Allocated) {
+			continue;
+		}
+	
+		for (Slot = CpciInfos->StartSlotNum[Bus];
+				Slot <= CpciInfos->EndSlotNum[Bus]; Slot++) {
+			switch (CpciEnumCheckAndClear(Slot, 0)) {
+			case CPCI_ENUM_INS:
+				/* As a sanity check see if it has already
+				 * been allocated.  This error condition
+				 * appears on cpv8540 boards when the the
+				 * system is booted and the latch is in
+				 * the down posiiton.
+				 */
+				if (CpciSlots[Slot].Allocated == CPCI_SLOT_ALLOCATED) {
+					return;
+				}
+
+				spin_lock_irqsave(&CpciPciAccessLock, flags);
+				CpciAddSlot(Slot);
+				spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+				return;
+
+			case CPCI_ENUM_EXT:
+				spin_lock_irqsave(&CpciPciAccessLock, flags);
+				CpciDelSlot(Slot);
+				spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+				return;
+			}
+		}
+	}
+	return;
+}
+
+void
+CpciHandleEnumTimeOutFunc(unsigned long arg)
+{
+	wake_up(&CpciHandleEnumWaitQ);
+	return;
+}
+
+void
+CpciFindDriver(struct pci_dev *dev)
+{
+	struct pci_driver *Drv;
+	struct list_head *ln;
+
+	for(ln=pci_drivers.next; ln != &pci_drivers; ln=ln->next) {
+		Drv = list_entry(ln, struct pci_driver, node);
+		if (Drv->remove && pci_announce_device(Drv, dev)) {
+			return;
+		}
+	}
+
+	/* Did not find an existing device driver so request one be inserted */
+	EventSendEvent(CpciEventId, 0,
+			CpciHsiEventClass, CPCI_EVENT_INSERT,
+			dev->vendor, dev->device,
+			dev->subsystem_vendor, dev->subsystem_device,
+			0, NULL);
+
+	return;
+}
+
+char *
+CpciGetName(struct pci_dev *dev)
+{
+	struct net_device *net_dev;
+
+	if ((dev->class >> 8) == PCI_CLASS_NET_ETH) {
+		if ((net_dev = (struct net_device *)dev->driver_data) != NULL) {
+			return net_dev->name;
+		}
+	}
+
+	return "dummy";
+}
+
+void
+CpciRegisterDevice(struct pci_dev *dev)
+{
+	int Slot = dev->cpci_location >> 16;
+	char *name;
+
+	if (dev->bus->number < CpciBuses[0].FirstBusNo) {
+		/* Not a cPCI device so do not register */
+		return;
+	}
+
+	CpciSlots[Slot].UseCount++;
+
+	name = CpciGetName(dev);
+
+	EventSendEvent(CpciEventId, 0,
+			CpciHsiEventClass, CPCI_EVENT_AVAIL,
+			Slot, dev->cpci_location & 0xffff, dev->class >> 8, 0,
+			strlen(name) + 1, name);
+	return;
+}
+
+void
+CpciUnRegisterDevice(struct pci_dev *dev)
+{
+	int Bus = 0;
+	struct pci_dev *Dev;
+	int Slot = dev->cpci_location >> 16;
+	char *name;
+
+	CpciSlots[Slot].UseCount--;
+
+	if (!(CpciSlots[Slot].UseCount & CPCI_ENUM_EXTRACT)) {
+		return;
+	}
+
+	name = CpciGetName(dev);
+
+	EventSendEvent(CpciEventId, 0,
+			CpciHsiEventClass, CPCI_EVENT_CLOSED,
+			Slot, dev->cpci_location & 0xffff, dev->class >> 8, 0,
+			strlen(name) + 1, name);
+
+	/* if this is a device only card with no bride this will be deleted
+	 * below because use count will go to zero.
+	 */
+	if (!((dev->bus->number == CpciSlots[Slot].Bus) &&
+	     (dev->devfn == CpciSlots[Slot].DevFn))) {
+#ifdef CONFIG_PROC_FS
+		pci_proc_detach_device(dev);
+#endif
+		list_del(&dev->bus_list);
+		list_del(&dev->global_list);
+		CpciFreeResources(dev);
+		kfree(dev);
+	}
+
+	if ((CpciSlots[Slot].UseCount & 0xffff) == 0) {
+
+		if ((Slot >= CpciInfos->StartSlotNum[0]) &&
+					(Slot <= CpciInfos->EndSlotNum[0])) {
+			Bus = 0;
+		} else if ((Slot >= CpciInfos->StartSlotNum[1]) &&
+					(Slot <= CpciInfos->EndSlotNum[1])) {
+			Bus = 1;
+		}
+
+		Dev = pci_find_slot(CpciBuses[Bus].FirstBusNo, CpciSlots[Slot].DevFn);
+
+#ifdef CONFIG_PROC_FS
+		pci_proc_detach_device(Dev);
+#endif
+		list_del(&Dev->bus_list);
+		list_del(&Dev->global_list);
+		CpciFreeResources(Dev);
+		kfree(Dev);
+
+		CpciSlots[Slot].Allocated = CPCI_SLOT_FREE;
+
+		EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_REM_SUCC,
+						Slot, 0, 0, 0, 0, NULL);
+		CpciTurnBlueLedOn(Slot);
+	}
+
+	return;
+}
+
+int
+CpciFindSlotFromDev(struct pci_dev *dev)
+{
+	int Slot;
+
+	for (Slot = 0; Slot < 16; Slot++) {
+		if (((dev->bus->number >= CpciSlots[Slot].FirstBusNo) &&
+		     (dev->bus->number <= CpciSlots[Slot].LastBusNo)) ||
+		    ((dev->bus->number == CpciSlots[Slot].Bus) &&
+		     (dev->devfn == CpciSlots[Slot].DevFn))) {
+			return Slot;
+		}
+	}
+
+	return -1;
+}
+
+void
+CpciSendAddSlotFail(int slot, int domain, int code)
+{
+	struct pci_controller *Hose = CpciSlots[slot].Hose;
+	int Bus = CpciBuses[domain].FirstBusNo;
+	int ProbeDevFn = CpciSlots[slot].DevFn;
+	unsigned short Command;
+	unsigned char SubBus;
+
+	/* Disable access to io and memory space to prevent this board from
+	 * responding.
+	 */
+	early_read_config_word(Hose, Bus, ProbeDevFn, PCI_COMMAND, &Command);
+	Command &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+	early_write_config_word(Hose, Bus, ProbeDevFn, PCI_COMMAND, Command);
+
+	early_read_config_byte(Hose, Bus, ProbeDevFn, PCI_SECONDARY_BUS, &SubBus);
+	early_write_config_byte(Hose, Bus, ProbeDevFn, PCI_SUBORDINATE_BUS, SubBus);
+	CpciSlots[slot].Allocated = CPCI_SLOT_INSFAILED;
+	CpciSlots[slot].Allocated |= code << 8;
+
+	EventSendEvent(CpciEventId, 0, CpciHsiEventClass, CPCI_BOARD_INS_FAIL,
+					slot, code, 0, 0, 0, NULL);
+
+	return;
+}
+
+int
+CpciFillInSlotInfo(CpciIoctlSlotInfo *slotInfo)
+{
+	struct pci_dev *Dev;
+	int Domain = slotInfo->Domain;
+	int Slot = slotInfo->Slot;
+	int SubDev = 0;
+
+	if ((Domain < 0) || (Domain >= CpciInfos->MaxBusNum)) {
+		return -EINVAL;
+	}
+
+	if ((Slot < CpciInfos->StartSlotNum[Domain]) ||
+	    (Slot > CpciInfos->EndSlotNum[Domain])) {
+		return -EINVAL;
+	}
+
+	pci_for_each_dev(Dev) {
+		if (Slot == CpciFindSlotFromDev(Dev)) {
+			if ((Dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+				continue;
+			}
+
+			slotInfo->DevInfo[SubDev].Vendor = Dev->vendor;
+			slotInfo->DevInfo[SubDev].Device = Dev->device;
+			slotInfo->DevInfo[SubDev].SubSystemVendor = Dev->subsystem_vendor;
+			slotInfo->DevInfo[SubDev].SubSystemDevice = Dev->subsystem_device;
+			slotInfo->DevInfo[SubDev].Class = Dev->class >> 8;
+			slotInfo->DevInfo[SubDev].Name[0] = '\0';
+
+			if (Dev->driver && Dev->driver->remove) {
+				if (Dev->driver_data != NULL) {
+					strncpy (slotInfo->DevInfo[SubDev].Name, CpciGetName(Dev), CPCI_MAX_NAME_LEN);
+				}
+				slotInfo->DevInfo[SubDev].DriverStatus = CPCI_DRIVER_INSTALLED;
+			} else {
+				slotInfo->DevInfo[SubDev].DriverStatus = CPCI_DRIVER_NEEDED;
+			}
+			SubDev++;
+
+			if (SubDev == CPCI_MAX_SLOT_INFO) {
+				slotInfo->NumSubDevs = CPCI_MAX_SLOT_INFO;
+				return 0;
+			}
+		}
+	}
+
+	slotInfo->NumSubDevs = SubDev;
+	return 0;
+}
+
+/* Functions to be accessed from modules. */
+EXPORT_SYMBOL(CpciRegisterDevice);
+EXPORT_SYMBOL(CpciUnRegisterDevice);
diff -u -r --new-file linux/drivers/ha/cpci/cpci_core.h ha/drivers/ha/cpci/cpci_core.h
--- linux/drivers/ha/cpci/cpci_core.h	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/cpci_core.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,118 @@
+/*
+ * cpci_core.h
+ *
+ * Header file defining dependencies in most of the core cPCI routines.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ */
+
+/* We currently handle ... */
+#define CPCI_MAX_BUSNUM		2	/* Mot 8221 chassis has 2 busses */
+#define CPCI_MAX_SLOTNUM	16	/* Mot 8216 chassis has 16 slots */
+
+/* A couple of useful defines */
+#define CPCI_BIT_SET	1
+#define CPCI_BIT_CLEAR	0
+
+/* Possible types of ENUM values */
+#define CPCI_ENUM_NONE 0
+#define CPCI_ENUM_INS  1
+#define CPCI_ENUM_EXT  2
+
+/* Calls to the enum control routines. */
+int  CpciEnumInsCheckAndClear(int);
+int  CpciEnumExtCheckAndClear(int);
+int  CpciTurnBlueLedOn(int);
+int  CpciEnumCheckAndClear(int, int);
+
+/* Core cPCI functionality that may be used by device dependant routines. */
+int  CpciConfigCpciBridge(struct pci_controller *, int, int, int);
+int  CpciConfigSlot(int, struct pci_controller *, int);
+void CpciSetupBus(int);
+void CpciFreeResources(struct pci_dev *);
+void CpciHssdFindDriver(struct pci_dev *);
+int  CpciFindSlotFromDev(struct pci_dev *);
+void CpciRegisterOpenCheck(struct pci_dev *);
+void CpciHssdPostInsert(unsigned short, unsigned short, unsigned short,
+			unsigned short, unsigned short);
+
+/* Debug functions. */
+void dump_bridge_reg(struct pci_controller *, int, int);
+void dump_busses(struct list_head *, int);
+void dump_devices(void);
+
+/* This structure defines the device dependant cPCI functions 
+ * required by the core cPCI code.
+ */
+typedef struct cpci_func {
+	int (*AllocAndInitBus)(int);
+	void (*DeallocAndShutdownBus)(int);
+	int (*SetEnumMask)(int, int);
+	int (*CheckHealthy)(int);
+	void (*MapIrq)(struct pci_dev *);
+} CpciFunc;
+
+extern CpciFunc *CpciFunctions;
+
+/* Define system dependent PCI node info to be fed to the system independant
+ * routines.
+ */
+typedef struct _CpciNodeInfo {
+	struct pci_controller *Hose;
+	int	Bus;
+	int	DevFn;
+	int	Allocated;
+	int	UseCount;		/* High bit indicates enum extract. */
+	int	FirstBusNo;
+	int	LastBusNo;
+	unsigned int IoStart;
+	unsigned int IoEnd;
+	unsigned int MemStart;
+	unsigned int MemEnd;
+} CpciNodeInfo;
+
+#define CPCI_ENUM_EXTRACT	0x80000000
+
+/* General system dependent info about chassis needed. */
+typedef struct _CpciInfo {
+	int	ChassisType;
+	int	MaxBusNum;
+	int	StartSlotNum[CPCI_MAX_BUSNUM];
+	int	EndSlotNum[CPCI_MAX_BUSNUM];
+} CpciInfo;
+
+/* Pointers to be filled out by system dependat code giving access to
+ * independant routines.
+ */
+extern CpciNodeInfo *CpciBuses;
+extern CpciNodeInfo *CpciSlots;
+extern CpciInfo *CpciInfos;
+
+#define PCI_CLASS_NET_ETH 0x0200
+
diff -u -r --new-file linux/drivers/ha/cpci/cpci_debug.c ha/drivers/ha/cpci/cpci_debug.c
--- linux/drivers/ha/cpci/cpci_debug.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/cpci_debug.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,189 @@
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_auto.h>
+#include <linux/cpci.h>
+#include <asm/pci.h>
+#include <asm/delay.h>
+#include "cpci_core.h"
+
+extern struct list_head pci_devices;
+
+void
+dump_bridge_reg(struct pci_controller *hose, int bus, int devfn)
+{
+	unsigned char tbt;
+	unsigned short twd;
+	unsigned int tdwd;
+
+	printk("Dump registers for bride at hose 0x%x bus 0x%x devfn 0x%x\n",
+			(unsigned int)hose, bus, devfn);
+
+	early_read_config_word(hose, bus, devfn, PCI_VENDOR_ID, &twd);
+	printk("Vendor: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_DEVICE_ID, &twd);
+	printk("Device: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_COMMAND, &twd);
+	printk("Command: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_STATUS, &twd);
+	printk("Status: 0x%x\n", twd);
+
+	early_read_config_dword(hose, bus, devfn, PCI_CLASS_REVISION, &tdwd);
+	printk("Class: 0x%x\n", tdwd >> 16);
+
+	early_read_config_byte(hose, bus, devfn, PCI_CACHE_LINE_SIZE, &tbt);
+	printk("Cache Line: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_LATENCY_TIMER, &tbt);
+	printk("Latency: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_HEADER_TYPE, &tbt);
+	printk("Header: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_BIST, &tbt);
+	printk("Bist: 0x%x\n", tbt);
+
+	early_read_config_dword(hose, bus, devfn, PCI_BASE_ADDRESS_0, &tdwd);
+	printk("Bar0: 0x%x\n", tdwd);
+
+	early_read_config_dword(hose, bus, devfn, PCI_BASE_ADDRESS_1, &tdwd);
+	printk("Bar1: 0x%x\n", tdwd);
+
+	early_read_config_byte(hose, bus, devfn, PCI_PRIMARY_BUS, &tbt);
+	printk("Primary: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_SECONDARY_BUS, &tbt);
+	printk("Second: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_SUBORDINATE_BUS , &tbt);
+	printk("Subord: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_SEC_LATENCY_TIMER, &tbt);
+	printk("Sec Lat: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_IO_BASE, &tbt);
+	printk("IO Base: 0x%x\n", tbt);
+
+	early_read_config_byte(hose, bus, devfn, PCI_IO_LIMIT, &tbt);
+	printk("IO Limit: 0x%x\n", tbt);
+
+	early_read_config_word(hose, bus, devfn, PCI_SEC_STATUS, &twd);
+	printk("Sec status: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_MEMORY_BASE, &twd);
+	printk("Mem Base: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_MEMORY_LIMIT, &twd);
+	printk("Mem Limit: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_PREF_MEMORY_BASE, &twd);
+	printk("Pre Mem Base: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_PREF_MEMORY_LIMIT, &twd);
+	printk("Pre Mem Limit: 0x%x\n", twd);
+
+	early_read_config_dword(hose, bus, devfn, PCI_PREF_BASE_UPPER32, &tdwd);
+	printk("Pre Upper Base: 0x%x\n", tdwd);
+
+	early_read_config_dword(hose, bus, devfn, PCI_PREF_LIMIT_UPPER32, &tdwd);
+	printk("Pre Upper Limit: 0x%x\n", tdwd);
+
+	early_read_config_word(hose, bus, devfn, PCI_IO_BASE_UPPER16, &twd);
+	printk("IO Upper Base: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_IO_LIMIT_UPPER16, &twd);
+	printk("IO Upper Limit: 0x%x\n", twd);
+
+	early_read_config_word(hose, bus, devfn, PCI_BRIDGE_CONTROL, &twd);
+	printk("Bridge Control: 0x%x\n", twd);
+
+}
+
+void
+dump_busses(struct list_head *plh, int level)
+{
+	struct list_head *ln, *devln;
+	struct pci_bus *check_bus;
+	struct pci_dev *check_dev;
+	int lev;
+	int i;
+
+	for (ln = plh->next; ln != plh; ln=ln->next) {
+		check_bus = pci_bus_b(ln);
+		for (lev = 0; lev < level; lev++) {
+			printk("    ");
+		}
+
+		printk("***** Bus vend 0x%x device 0x%x number 0x%x primary 0x%x second 0x%x subord 0x%x\n",
+			check_bus->vendor, check_bus->device, check_bus->number,
+			check_bus->primary, check_bus->secondary, check_bus->subordinate);
+
+		for (lev = 0; lev < level; lev++) {
+			printk("    ");
+		}
+
+		
+		printk("resources ");
+		for (i=0; i < 4; i++) {
+			if (check_bus->resource[i]) {
+				printk("0x%x:0x%x ",
+					(unsigned int)check_bus->resource[i]->start,
+					(unsigned int)check_bus->resource[i]->end);
+			}
+		}
+		printk("\n");
+
+		printk("Devices on bus:\n");
+		for (devln = check_bus->devices.next;
+			devln != &check_bus->devices; devln = devln->next) {
+			check_dev = pci_dev_b(devln);
+			printk("name '%s' bus 0x%x devfn 0x%x vendor 0x%x device 0x%x\n",
+				check_dev->name, check_dev->bus->number,
+				check_dev->devfn, check_dev->vendor,
+				check_dev->device);
+			printk("Resources 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x\n",
+				(unsigned int)check_dev->resource[0].start,
+				(unsigned int)check_dev->resource[0].end,
+				(unsigned int)check_dev->resource[1].start,
+				(unsigned int)check_dev->resource[1].end,
+				(unsigned int)check_dev->resource[2].start,
+				(unsigned int)check_dev->resource[2].end,
+				(unsigned int)check_dev->resource[3].start,
+				(unsigned int)check_dev->resource[3].end);
+		}
+
+		dump_busses(&check_bus->children, level + 1);
+	}
+}
+
+void
+dump_devices(void)
+{
+	struct list_head *n = pci_devices.next;
+	struct pci_dev *check_dev;
+
+	printk("Dump Devices\n");
+	while (n != &pci_devices) {
+		check_dev = pci_dev_g(n);
+
+		printk("name '%s' bus 0x%x devfn 0x%x vendor 0x%x device 0x%x\n",
+				check_dev->name, check_dev->bus->number,
+				check_dev->devfn, check_dev->vendor,
+				check_dev->device);
+		printk("Resources 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x 0x%x:0x%x\n",
+				(unsigned int)check_dev->resource[0].start,
+				(unsigned int)check_dev->resource[0].end,
+				(unsigned int)check_dev->resource[1].start,
+				(unsigned int)check_dev->resource[1].end,
+				(unsigned int)check_dev->resource[2].start,
+				(unsigned int)check_dev->resource[2].end,
+				(unsigned int)check_dev->resource[3].start,
+				(unsigned int)check_dev->resource[3].end);
+
+		n = n->next;
+	}
+}
+
diff -u -r --new-file linux/drivers/ha/cpci/cpci_enum.c ha/drivers/ha/cpci/cpci_enum.c
--- linux/drivers/ha/cpci/cpci_enum.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/cpci_enum.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,352 @@
+/*
+ * cpci_carrier.c
+ *
+ * Routines for recognizing the type and controlling ENUM for cPCI carriers.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_auto.h>
+#include <linux/cpci.h>
+#include <asm/pci.h>
+#include <asm/delay.h>
+#include "cpci_core.h"
+
+#define CPCI_BOARD_TYPE_UNKNOWN 0
+#define CPCI_BOARD_TYPE_2_12_STANDARD 1
+#define CPCI_BOARD_TYPE_ALT_CPV8540 2
+
+#define CPCI_HS_CAPABILITY_ID 0x6
+
+#define CPCI_BRD_TYPE(x) ((x) & 0xff)
+#define CPCI_BRD_CAPPTR(x) ((x >> 8) & 0xff)
+
+/* Prototypes for 2.12 compliant boards. */
+static int  picmg2_12_clear_ins_enum(struct pci_controller *, int, int, unsigned char);
+static int  picmg2_12_clear_ext_enum(struct pci_controller *, int, int, unsigned char);
+static void picmg2_12_blue_led_on(struct pci_controller *, int, int, unsigned char);
+
+/* Prototypes for Motorola CPV8540 carrier boards. */
+static int  cpv8540_clear_ins_enum(struct pci_controller *, int, int, unsigned char);
+static int  cpv8540_clear_ext_enum(struct pci_controller *, int, int, unsigned char);
+static void cpv8540_blue_led_on(struct pci_controller *, int, int, unsigned char);
+
+/* Board specific function array. */
+typedef struct cpci_carrier_board_info {
+        int  (*ClearInsEnum)(struct pci_controller *, int, int, unsigned char);
+        int  (*ClearExtEnum)(struct pci_controller *, int, int, unsigned char);
+        void (*BlueLightOn)(struct pci_controller *, int, int, unsigned char);
+} CpciCarrierInfoStruct;
+
+CpciCarrierInfoStruct CpciCarrierInfo[] = {
+	{NULL, NULL, NULL},	/* Element 0 is an error condition */
+	{picmg2_12_clear_ins_enum, picmg2_12_clear_ext_enum, picmg2_12_blue_led_on},
+	{cpv8540_clear_ins_enum, cpv8540_clear_ext_enum, cpv8540_blue_led_on}
+};
+
+/*
+ * Return the board type.  At the moment the only board we have is
+ * the Mot CPV8540.  If the bridge found is a Dec 211454 assume it is
+ * this board.
+ */
+int
+CpciEnumGetBrdType(struct pci_controller *hose, int bus, int devfn)
+{
+	unsigned short Status;
+	unsigned short Vendor;
+	unsigned short Device;
+	unsigned short SubVendor;
+	unsigned short SubDevice;
+	unsigned char CapPtr;
+	int Capability;
+
+	early_read_config_word(hose, bus, devfn, PCI_VENDOR_ID, &Vendor);
+	early_read_config_word(hose, bus, devfn, PCI_DEVICE_ID, &Device);
+	early_read_config_word(hose, bus, devfn, PCI_SUBSYSTEM_VENDOR_ID, &SubVendor);
+	early_read_config_word(hose, bus, devfn, PCI_SUBSYSTEM_ID, &SubDevice);
+
+	if ((Vendor == PCI_VENDOR_ID_DEC) && (Device == PCI_DEVICE_ID_DEC_21154)) {
+		return CPCI_BOARD_TYPE_ALT_CPV8540;
+	}
+
+	early_read_config_word(hose, bus, devfn, PCI_STATUS, &Status);
+
+	if (Status == 0xffff) {
+		/* Nothing to read in this slot. */
+		return CPCI_BOARD_TYPE_UNKNOWN;
+	}
+
+	if (Status & PCI_STATUS_CAP_LIST) {
+		early_read_config_byte(hose, bus, devfn, PCI_CAPABILITY_LIST, &CapPtr);
+		while (CapPtr) {
+			early_read_config_dword(hose, bus, devfn, CapPtr, &Capability);
+			if ((Capability & 0xff) == CPCI_HS_CAPABILITY_ID) {
+				return ((CapPtr << 8) | CPCI_BOARD_TYPE_2_12_STANDARD);
+			}
+
+			CapPtr = (Capability >> 8) & 0xff;
+		}
+	}
+
+	return CPCI_BOARD_TYPE_UNKNOWN;
+}
+
+/*
+ * Check and see if an insert enum exists and clear it if so.
+ */
+int
+CpciEnumCheckAndClear(int slot, int extractOnly)
+{
+	int BrdType;
+
+	BrdType = CpciEnumGetBrdType(CpciSlots[slot].Hose,
+				CpciSlots[slot].Bus, CpciSlots[slot].DevFn);
+
+	if (CPCI_BRD_TYPE(BrdType) == CPCI_BOARD_TYPE_UNKNOWN) {
+		return 0;
+	}
+
+	if (CpciCarrierInfo[CPCI_BRD_TYPE(BrdType)].ClearExtEnum(CpciSlots[slot].Hose,
+				CpciSlots[slot].Bus, CpciSlots[slot].DevFn,
+				CPCI_BRD_CAPPTR(BrdType))) {
+		return CPCI_ENUM_EXT;
+	}
+
+	if (extractOnly) {
+		return CPCI_ENUM_NONE;
+	}
+
+	if (CpciCarrierInfo[CPCI_BRD_TYPE(BrdType)].ClearInsEnum(CpciSlots[slot].Hose,
+				CpciSlots[slot].Bus, CpciSlots[slot].DevFn,
+				CPCI_BRD_CAPPTR(BrdType))) {
+		return CPCI_ENUM_INS;
+	}
+
+	return CPCI_ENUM_NONE;
+}
+
+/*
+ * Turn the blue light on to signal extraction OK.
+ */
+int
+CpciTurnBlueLedOn(int slot)
+{
+	int BrdType;
+
+	BrdType = CpciEnumGetBrdType(CpciSlots[slot].Hose,
+				CpciSlots[slot].Bus, CpciSlots[slot].DevFn);
+
+	if (CPCI_BRD_TYPE(BrdType) == CPCI_BOARD_TYPE_UNKNOWN) {
+		return 0;
+	}
+
+	CpciCarrierInfo[CPCI_BRD_TYPE(BrdType)].BlueLightOn(CpciSlots[slot].Hose,
+				CpciSlots[slot].Bus, CpciSlots[slot].DevFn,
+				CPCI_BRD_CAPPTR(BrdType));
+	return 0;
+}
+
+#define CPCI_HS_DEV_HIDE_BIT 0x10000
+#define CPCI_HS_ENUMSIG_BIT  0x20000
+#define CPCI_HS_PEND_BIT     0x40000
+#define CPCI_HS_BLUELED_BIT  0x80000
+#define CPCI_HS_PIE_BIT      0x100000
+#define CPCI_HS_EXT_ENUM_BIT 0x400000
+#define CPCI_HS_INS_ENUM_BIT 0x800000
+
+static int
+picmg2_12_clear_ins_enum(struct pci_controller *hose,
+			 int bus, int devfn, unsigned char capPtr)
+{
+	int Capability;
+
+	early_read_config_dword(hose, bus, devfn, capPtr, &Capability);
+
+	if((Capability & 0xff) != CPCI_HS_CAPABILITY_ID) {
+		/* Something strange has happened */
+		return 0;
+	}
+
+	if (Capability & CPCI_HS_INS_ENUM_BIT) {
+		/* Found an insert enum */
+		early_write_config_dword(hose, bus, devfn, capPtr, CPCI_HS_INS_ENUM_BIT);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+picmg2_12_clear_ext_enum(struct pci_controller *hose,
+			 int bus, int devfn, unsigned char capPtr)
+{
+	int Capability;
+
+	early_read_config_dword(hose, bus, devfn, capPtr, &Capability);
+
+	if((Capability & 0xff) != CPCI_HS_CAPABILITY_ID) {
+		/* Something strange has happened */
+		return 0;
+	}
+
+	if (Capability & CPCI_HS_EXT_ENUM_BIT) {
+		/* Found an extract enum.  Turn off the extract enum
+		 * bit but leave the blue light off and mask the enum
+		 * signal generation from this slot.  The blue light
+		 * will be turned off and enum signal restored when]
+		 * the drivers have quiesed and returned.
+		 */
+		early_read_config_dword(hose, bus, devfn, capPtr, &Capability);
+		if (Capability & CPCI_HS_BLUELED_BIT) {
+			early_write_config_dword(hose, bus, devfn, capPtr, CPCI_HS_BLUELED_BIT);
+			early_read_config_dword(hose, bus, devfn, capPtr, &Capability);
+		}
+
+		if (!(Capability & CPCI_HS_ENUMSIG_BIT)) {
+			early_write_config_dword(hose, bus, devfn, capPtr, CPCI_HS_ENUMSIG_BIT);
+		}
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static void
+picmg2_12_blue_led_on(struct pci_controller *hose,
+		      int bus, int devfn, unsigned char capPtr)
+{
+	int Capability;
+
+	early_read_config_dword(hose, bus, devfn, capPtr, &Capability);
+
+	if((Capability & 0xff) != CPCI_HS_CAPABILITY_ID) {
+		/* Something strange has happened */
+		return;
+	}
+
+	if (!(Capability & CPCI_HS_BLUELED_BIT)) {
+		early_write_config_dword(hose, bus, devfn, capPtr, CPCI_HS_BLUELED_BIT);
+	}
+
+	if (Capability & CPCI_HS_ENUMSIG_BIT) {
+		early_write_config_dword(hose, bus, devfn, capPtr, CPCI_HS_ENUMSIG_BIT);
+	}
+
+	early_write_config_dword(hose, bus, devfn, capPtr, CPCI_HS_EXT_ENUM_BIT);
+
+	return;
+}
+
+#define CPV8540_INIT_BYTE	0x65
+#define CPV8540_ENUM_CONTROL	0x66
+#define CPV8540_ENUM_STATUS	0x67
+
+#define CPV8540_INS		0x80
+#define CPV8540_EXT		0x40
+
+#define CPV8540_INIT1		0x0f
+#define CPV8540_INIT2		0x3c
+#define CPV8540_INS_RESET	0x08
+#define CPV8540_EXT_RESET	0x04
+
+#define CPV8540_BLUELED_ON	0x20
+#define CPV8540_BLUELED_OFF	0x02
+
+#define CPV8540_ENUM_ENABLE	0x01
+#define CPV8540_ENUM_DISABLE	0x10
+
+static int
+cpv8540_clear_ins_enum(struct pci_controller *hose,
+		       int bus, int devfn, unsigned char capPtr)
+{
+	unsigned char HSBits;
+
+	early_write_config_byte(hose, bus, devfn, CPV8540_ENUM_CONTROL, CPV8540_INIT2);
+
+	early_read_config_byte(hose, bus, devfn, CPV8540_ENUM_STATUS, &HSBits);
+
+	if (HSBits & CPV8540_INS) {
+		early_write_config_byte(hose, bus, devfn,
+					CPV8540_ENUM_CONTROL, CPV8540_INS);
+		early_write_config_byte(hose, bus, devfn,
+					CPV8540_ENUM_CONTROL, CPV8540_INS_RESET);
+
+		early_write_config_byte(hose, bus, devfn, CPV8540_INIT_BYTE, CPV8540_INIT1);
+		return 1;
+	}
+
+	return 0;
+}
+
+static int
+cpv8540_clear_ext_enum(struct pci_controller *hose,
+		       int bus, int devfn, unsigned char capPtr)
+{
+	unsigned char HSBits;
+
+	early_read_config_byte(hose, bus, devfn, CPV8540_ENUM_STATUS, &HSBits);
+
+	if (HSBits & CPV8540_EXT) {
+		early_write_config_byte(hose, bus, devfn,
+					CPV8540_ENUM_CONTROL, CPV8540_EXT);
+		early_write_config_byte(hose, bus, devfn,
+					CPV8540_ENUM_CONTROL, CPV8540_EXT_RESET);
+
+		/* Turn the Blue light back off.  We wanted to clear the enum
+		 * but not the blue light.  Blue light will be cleared when
+		 * the drivers have queiesced and it is OK to pull the board.
+	 	 */
+		early_write_config_byte(hose, bus, devfn,
+					CPV8540_INIT_BYTE, CPV8540_BLUELED_OFF);
+
+		/* While quiesce in in progress inhibit ENUM generation. */
+		early_write_config_byte(hose, bus, devfn,
+					CPV8540_INIT_BYTE, CPV8540_ENUM_DISABLE);
+
+		return 1;
+	}
+
+	return 0;
+}
+
+static void
+cpv8540_blue_led_on(struct pci_controller *hose,
+		    int bus, int devfn, unsigned char capPtr)
+{
+	early_write_config_byte(hose, bus, devfn,
+				CPV8540_INIT_BYTE, CPV8540_BLUELED_ON);
+
+	early_write_config_byte(hose, bus, devfn,
+				CPV8540_INIT_BYTE, CPV8540_ENUM_ENABLE);
+}
diff -u -r --new-file linux/drivers/ha/cpci/mot82XXhsc.c ha/drivers/ha/cpci/mot82XXhsc.c
--- linux/drivers/ha/cpci/mot82XXhsc.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/mot82XXhsc.c	Thu Dec 13 13:26:13 2001
@@ -0,0 +1,2483 @@
+/*
+ * mot82XXhsc.c
+ *
+ * Motorola 82XX hot swap controller driver.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/fs.h>
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#include "mot82XXhsc.h"
+#include "phs.h"
+
+/* Driver entrance function prototypes. */
+static ssize_t	mot82XXhsc_read(struct file *, char *, size_t, loff_t *);
+static int	mot82XXhsc_ioctl(struct inode *, struct file *,
+	                        unsigned int, unsigned long);
+static int	mot82XXhsc_open(struct inode *, struct file *);
+static int	mot82XXhsc_release(struct inode *, struct file *);
+static int	mot82XXhsc_fasync(int, struct file *, int);
+static void	mot82XXhsc_intr(int, void *, struct pt_regs *);
+
+/* Functions used for interrupt handling. */
+static void	mot82XXhscMapIntBitsToRegisters(void);
+static void	mot82XXhscHandleSlotInt(volatile unsigned int *, int);
+static void	mot82XXhscHandleHostInt(volatile unsigned int *, int);
+static void	mot82XXhscHandleHSCInt(volatile unsigned int *, int);
+static void	mot82XXhscHandlePbayInt(volatile unsigned int *, int);
+static void	mot82XXhscHandleMaskInt(volatile unsigned int *, int);
+static void	mot82XXhscHandlePSInt(volatile unsigned int *, int);
+static void	mot82XXhscHandleAlarmInt(volatile unsigned int *, int);
+static void	mot82XXhscHandleBusInt(volatile unsigned int *, int);
+
+/* Sub functions called by the ioctl system call */
+static int	mot82XXhscGetRegs(unsigned long);
+static int	mot82XXhscGetEvents(unsigned long);
+static int	mot82XXhscSetAlarm(unsigned int, unsigned int);
+static int	mot82XXhscGetAlarm(unsigned long);
+static int	mot82XXhscSetLed(unsigned int, unsigned int);
+static int	mot82XXhscGetLed(unsigned long);
+static int	mot82XXhscSetPBay(unsigned long);
+static int	mot82XXhscGetPBay(unsigned long);
+static int	mot82XXhscSetPS(unsigned long);
+static int	mot82XXhscGetPS(unsigned long);
+static int	mot82XXhscGetLocalHost(unsigned long);
+static int	mot82XXhscGetBusState(unsigned long);
+static int	mot82XXhscTakeBus(unsigned long);
+static int	mot82XXhscFreeBus(unsigned long);
+static int	mot82XXhscAllowBusTake(unsigned long);
+static int	mot82XXhscGetEnumMask(unsigned long);
+static int	mot82XXhscGetEnum(unsigned long);
+static int	mot82XXhscGetNonHost(unsigned long);
+static int	mot82XXhscSetNonHost(unsigned long);
+static int	mot82XXhscGetHost(unsigned long);
+static int	mot82XXhscSetHostst(unsigned long);
+static int	mot82XXhscGetHsc(unsigned long);
+static int	mot82XXhscSetHsc(unsigned long);
+
+/* Generally used suport functions */
+static int	mot82XXhscAttachBus(int, int);
+static int	mot82XXhscReleaseBus(int);
+void		mot82XXhscTakeTimeOutFunc(unsigned long);
+
+/* Functions to support the PICMG 2.12 ENUM# functionality. */
+int		mot82XXhscHsiInit(void);
+BOOLEAN		mot82XXhscHsiCheckEnumInterrupt(void *);
+BOOLEAN		mot82XXhscHsiQueryEnumState(void);
+HSI_STATUS	mot82XXhscHsiEnableEnums(void);
+HSI_STATUS	mot82XXhscHsiDisableEnums(void);
+int		mot82XXhscHsiConvertStatus(HSI_STATUS);
+
+/* Functions to be accessed from the PICMG 2.12 independent code */
+int		HsiThreadRegister(void);
+void		HsiPlatformEnumHandler(int, void *, struct pt_regs *);
+
+/* Functions to support the generic chassis managment API. */
+int		mot82xxChassisStatusFunc(unsigned int, unsigned int);
+int		mot82xxChassisAlarmFunc(unsigned int, unsigned int);
+
+/* Functions supporting delivery of events to user level requesters. */
+HscMessage	*mot82XXhscAllocMessage(void);
+void		mot82XXhscFreeMessage(HscMessage *);
+void		mot82XXhscSendEvent(int, int, int, int);
+
+/* Accessing the registers on the board. */
+static void	mot82XXhscClrBits(volatile unsigned int *, unsigned int);
+static void	mot82XXhscSetBits(volatile unsigned int *, unsigned int);
+
+/* Used in the bus status interrupt. */
+void motCpciSetDomainTakeover(int);
+
+/* Driver fops interface/ */
+static struct  file_operations mot82XXhsc_fops = {
+	read:		mot82XXhsc_read,
+	ioctl:		mot82XXhsc_ioctl,
+	open:		mot82XXhsc_open,
+	release:	mot82XXhsc_release,
+	fasync:		mot82XXhsc_fasync,
+};
+
+/* General driver internal information. */
+HscInfo MotHscInfo;
+HscStats MotHscStats;
+
+/* Eventing mechanism support data structures. */
+HscEventRequesters MotEventRequesters[MOTHSC_MAX_EVENT_REQUESTERS];
+HscEventRequesters *MotEventRequestersList = NULL;
+HscEventRequesters *MotEventRequestersFreeList;
+HscMessage *MotMessageFreeList;
+
+/* Bus take over time out control structure. */
+struct timer_list mot82XXhscTakeTimeOut;
+
+/*
+ * Driver init routine.
+ */
+int
+mot82XXhsc_init(void)
+{
+	int loop;
+	HscMessage *TmpMessPtr;
+	unsigned long Bits;
+	int State;
+
+	printk("Initialize the Motorola 82XX Hot Swap Controller\n");
+
+	/* Find the devices location information. */
+	MotHscInfo.Device = pci_find_device(PCI_VENDOR_ID_MOTOROLA,
+			PCI_DEVICE_ID_MOTOROLA_CPX8216, NULL);
+
+	if (!MotHscInfo.Device) {
+		MotHscInfo.Device = pci_find_device(PCI_VENDOR_ID_MOTOROLA,
+				PCI_DEVICE_ID_MOTOROLA_CPX8216T, NULL);
+	}
+
+	if (!MotHscInfo.Device) {
+		MotHscInfo.Device = pci_find_device(PCI_VENDOR_ID_MOTOROLA,
+				PCI_DEVICE_ID_MOTOROLA_CPX8216A, NULL);
+	}
+
+	if (!MotHscInfo.Device) {
+		MotHscInfo.Device = pci_find_device(PCI_VENDOR_ID_MOTOROLA,
+				PCI_DEVICE_ID_MOTOROLA_CPX8221, NULL);
+
+		if (MotHscInfo.Device) {
+			printk("mot82XXhsc: Motoroal 8221 Chassis not supported\n");
+			return -ENODEV;
+		}
+	}
+
+	if (!MotHscInfo.Device) {
+		printk("mot82XXhsc: Failed to find 82XX Hot Swap Controller\n");
+		return -ENODEV;
+	}
+
+	if ((MotHscInfo.Regs = (HscRegs *)ioremap(
+			pci_resource_start(MotHscInfo.Device, 0),
+			pci_resource_len(MotHscInfo.Device, 0))) == NULL) {
+		printk("mot82XXhsc: Ioremap failed\n");
+		return -EIO;
+	}
+
+	if (request_irq(MotHscInfo.Device->irq, (void *)&mot82XXhsc_intr,
+					SA_SHIRQ, "82XX HSC", &mot82XXhsc_fops)) {
+		printk("mot82XXhsc: Interrupt request failed\n");
+		iounmap((void *)MotHscInfo.Regs);
+		return -EIO;
+	}
+
+	if ((MotHscInfo.Major = register_chrdev(0, "82XX Hot Swap Controller",
+				&mot82XXhsc_fops)) < 0) {
+		printk("mot82XXhsc: Failed to register 82XX HSC\n");
+		free_irq(MotHscInfo.Device->irq, &mot82XXhsc_fops);
+		iounmap((void *)MotHscInfo.Regs);
+		return -ENODEV;
+	}
+
+	/* Initialize the event requesters free list */
+	for (loop = 0; loop <MOTHSC_MAX_EVENT_REQUESTERS; loop++) {
+		MotEventRequesters[loop].Next = 
+			(HscEventRequesters *)&MotEventRequesters[loop+1].Next;
+		
+		MotEventRequesters[loop].Pid = 0;
+		MotEventRequesters[loop].Head = (HscMessage *)NULL;
+		MotEventRequesters[loop].Tail = (HscMessage *)NULL;
+		MotEventRequesters[loop].Fasyncptr = (struct fasync_struct *)NULL;
+	}
+	MotEventRequesters[MOTHSC_MAX_EVENT_REQUESTERS-1].Next = 
+						(HscEventRequesters *)NULL;
+	MotEventRequestersFreeList = MotEventRequesters;
+	
+	/* Initialize the first chuch of memory for handling event messages */
+	MotMessageFreeList = kmalloc(MOTHSC_MESSAGE_CHUNK_SIZE *
+					sizeof(HscMessage), GFP_ATOMIC);
+
+	TmpMessPtr = MotMessageFreeList;
+	for (loop = 0; loop < MOTHSC_MESSAGE_CHUNK_SIZE-1; loop++) {
+		TmpMessPtr->Event = 0;
+		TmpMessPtr->Unit = 0;
+		TmpMessPtr->Val = 0;
+		TmpMessPtr->Next = TmpMessPtr + 1;
+		TmpMessPtr++;
+	}
+	TmpMessPtr->Event = 0;
+	TmpMessPtr->Unit = 0;
+	TmpMessPtr->Val = 0;
+	TmpMessPtr->Next = NULL;
+
+	/* Set up some pointers needed for interrupt handling. */
+	mot82XXhscMapIntBitsToRegisters();
+
+	/* Byt default do not allow the other host to take bus. */
+	MotHscInfo.BusTakeoverAllowed[0] = 0;
+	MotHscInfo.BusTakeoverAllowed[1] = 0;
+
+	/* Keep track of the last bus control register for later use */
+	MotHscInfo.LastBusControl[0] = MOTHSC_READREG(BusControl[0]);
+	MotHscInfo.LastBusControl[1] = MOTHSC_READREG(BusControl[1]);
+
+	/* Get the host for future information */
+	MotHscInfo.Host = (MotHscInfo.LastBusControl[0] &
+						MOTHSC_HOST_DOMAIN) >> 7;
+
+	/* Clear enum events for the moment */
+	mot82XXhscClrBits(&MotHscInfo.Regs->IntMask, MOTHSC_ENUMA);
+	mot82XXhscClrBits(&MotHscInfo.Regs->IntMask, MOTHSC_ENUMB);
+
+	/* Turn off the enum propigate bit */
+	mot82XXhscClrBits(&MotHscInfo.Regs->IntMask, MOTHSC_PROP_ENUM);
+
+	/* Save the state of the ENUM bits for future use */
+	MotHscInfo.EnumOldState[0] = MOTHSC_READREG(IntMask) & MOTHSC_A_STATE;
+	MotHscInfo.EnumOldState[1] = MOTHSC_READREG(IntMask) & MOTHSC_B_STATE;
+
+	/* Indicate that enums are disabled */
+	MotHscInfo.EnumEnabled[0] = 0;
+	MotHscInfo.EnumEnabled[1] = 0;
+
+	/* 
+	 * SANITY CHECK:
+	 * Do a little consistancy check.  If the bus state indicates the
+	 * bus is being taken away from us then give it up.  In the same
+	 * way, if We we in bus take over then finish the take over.  As
+	 * soon as this is all finishished the configuration software can
+	 * continue to get or give busses as needed.
+	 */
+	State = MOTHSC_READREG(BusControl[0]);
+	if ((State & (MOTHSC_XFR_CTL1|MOTHSC_XFR_CTL2)) == MOTHSC_XFR_CTL1) {
+		/* Currently in bus A being taken over by this host */
+		mot82XXhscSetBits(&MotHscInfo.Regs->BusControl[0],
+							MOTHSC_XFR_CTL2);
+	}
+
+	if ((State & (MOTHSC_XFR_STS1|MOTHSC_XFR_STS2)) == MOTHSC_XFR_STS1) {
+		/* Currently bus A being taken over by other host */
+		mot82XXhscClrBits(&MotHscInfo.Regs->BusControl[0],
+					MOTHSC_XFR_CTL1|MOTHSC_XFR_CTL2);
+	}
+
+	State = MOTHSC_READREG(BusControl[1]);
+	if ((State & (MOTHSC_XFR_CTL1|MOTHSC_XFR_CTL2)) == MOTHSC_XFR_CTL1) {
+		/* Currently in bus B being taken over by this host */
+		mot82XXhscSetBits(&MotHscInfo.Regs->BusControl[1],
+							MOTHSC_XFR_CTL2);
+	}
+
+	if ((State & (MOTHSC_XFR_STS1|MOTHSC_XFR_STS2)) == MOTHSC_XFR_STS1) {
+		/* Currently bus B being taken over by other host */
+		mot82XXhscClrBits(&MotHscInfo.Regs->BusControl[1],
+					MOTHSC_XFR_CTL1|MOTHSC_XFR_CTL2);
+	}
+
+	/* Set the host slots to generate interrupts and set the history */
+	mot82XXhscClrBits(&MotHscInfo.Regs->Slot[6], MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->Slot[6], MOTHSC_INTA_ENABLE);
+
+	mot82XXhscClrBits(&MotHscInfo.Regs->Slot[8], MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->Slot[8], MOTHSC_INTA_ENABLE);
+
+	Bits = MOTHSC_READREG(Slot[6]);
+	MotHscInfo.HostOldBits[6] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & ~MOTHSC_HOSTINT;
+	MotHscInfo.HostOldIntBits[6] = Bits & MOTHSC_HOSTINT;
+
+	Bits = MOTHSC_READREG(Slot[8]);
+	MotHscInfo.HostOldBits[8] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & ~MOTHSC_HOSTINT;
+	MotHscInfo.HostOldIntBits[8] = Bits & MOTHSC_HOSTINT;
+
+	/* Do the same for the HSC slots */
+	mot82XXhscClrBits(&MotHscInfo.Regs->Slot[7], MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->Slot[7], MOTHSC_INTA_ENABLE);
+
+	mot82XXhscClrBits(&MotHscInfo.Regs->Slot[9], MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->Slot[9], MOTHSC_INTA_ENABLE);
+
+	Bits = MOTHSC_READREG(Slot[7]);
+	MotHscInfo.HscOldBits[7] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & ~MOTHSC_HSCINT;
+	MotHscInfo.HscOldIntBits[7] = Bits & MOTHSC_HOSTINT;
+
+	Bits = MOTHSC_READREG(Slot[9]);
+	MotHscInfo.HscOldBits[9] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & ~MOTHSC_HSCINT;
+	MotHscInfo.HscOldIntBits[9] = Bits & MOTHSC_HOSTINT;
+
+	/* Set interrupts to occure from status register */
+	mot82XXhscClrBits(&MotHscInfo.Regs->IntMask, MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->IntMask, MOTHSC_INTA_ENABLE | MOTHSC_INTA);
+
+	/* Set interrupts to occur from alarm register */
+	mot82XXhscClrBits(&MotHscInfo.Regs->Alarm, MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->Alarm, MOTHSC_INTA_ENABLE);
+
+	/* Set interrupts to occur from system led register */
+	mot82XXhscClrBits(&MotHscInfo.Regs->SysLed, MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->SysLed, MOTHSC_INTA_ENABLE);
+
+	/* Set interrupts to occur from Peripheral bay registers */
+	for (loop = 0; loop < MOTHSC_NUM_PBAY; loop++) {
+		mot82XXhscClrBits(&MotHscInfo.Regs->PBay[loop], MOTHSC_INTC_ENABLE);
+		mot82XXhscSetBits(&MotHscInfo.Regs->PBay[loop], MOTHSC_INTA_ENABLE);
+
+		/* Keep track of the last bits in the peripheral bay registers */
+		MotHscInfo.PBayOldBits[loop] = MOTHSC_READREG(PBay[loop]);
+		MotHscInfo.PBayOldBits[loop] =
+				(MotHscInfo.PBayOldBits[loop] & 0x7) +
+				((MotHscInfo.PBayOldBits[loop] & 0x300) >> 5);
+	}
+
+	/* Set interrupts to occur from Power Supply registers */
+	for (loop = 0; loop < MOTHSC_NUM_PS; loop++) {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Ps[loop], MOTHSC_INTC_ENABLE);
+		mot82XXhscSetBits(&MotHscInfo.Regs->Ps[loop], MOTHSC_INTA_ENABLE);
+
+		/* Keep track of the last bits in the power supply registers */
+		MotHscInfo.PowerOldBits[loop] = MOTHSC_READREG(Ps[loop]);
+		MotHscInfo.PowerOldBits[loop] =
+				(MotHscInfo.PBayOldBits[loop] & 0x1f) +
+				((MotHscInfo.PBayOldBits[loop] & 0x7f00) >> 3);
+	}
+
+	/* Save off the status bits for slot controls. */
+	for (loop = 0; loop < MOTHSC_NUM_SLOTS; loop++) {
+		if ((loop > 5) && (loop < 10)) {
+			continue;
+		}
+
+		Bits = MOTHSC_READREG(Slot[loop]) & ~MOTHSC_SLOTINT;
+		MotHscInfo.SlotOldBits[loop] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & ~MOTHSC_SLOTINT;
+		MotHscInfo.SlotOldIntBits[loop] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & MOTHSC_SLOTINT;
+	}
+
+	/* Set up the timer queue for delayed take over of a bus */
+	init_timer(&mot82XXhscTakeTimeOut);
+	mot82XXhscTakeTimeOut.function = mot82XXhscTakeTimeOutFunc;
+
+	/* If the PICMG 2.12 interface has been enabled then init it. */
+	if (mot82XXhscHsiInit()) {
+		unregister_chrdev(MotHscInfo.Major, "82XX Hot Swap Controller");
+		free_irq(MotHscInfo.Device->irq, &mot82XXhsc_fops);
+		iounmap((void *)MotHscInfo.Regs);
+		return -ESRCH;
+	}
+
+	/* Start the PICMG 2.12 handling thread. */
+	HsiThreadRegister();
+
+#ifdef CONFIG_CHASSIS_CONTROL
+	/* Register chassis managment functions. */
+	ChassisRegSystemStatusFunc(mot82xxChassisStatusFunc);
+	ChassisRegAlarmFunc(mot82xxChassisAlarmFunc);
+#endif
+	return 0;
+}
+
+/*
+ * Linux read interface.
+ *
+ * Currently a null function.  Needs to be updated to provide some
+ * basic driver information.
+ */
+static ssize_t
+mot82XXhsc_read(struct file *file, char *buffer, size_t count, loff_t *ppos)
+{
+	return (ssize_t)0;
+}
+
+/*
+ * Linux ioctl interface.
+ *
+ * Most of the functionality of the driver is controlled through this
+ * interface.  The argument variable is passed directly to the sub
+ * functionality for most cases.  The exception is the ENUM mask set
+ * operation.  It is different to allow the function to used from other
+ * locations.
+ */
+static int
+mot82XXhsc_ioctl(struct inode *inode,
+	        struct file *file, unsigned int cmd, unsigned long arg)
+{
+	unsigned int EnumUser;
+	int bus;
+	int flag;
+	MotHscAlarmLedSet AlarmUser;
+
+	switch (cmd) {
+	case HSC_GET_REGISTERS:
+		return mot82XXhscGetRegs(arg);
+	case HSC_GET_EVENTS:
+		return mot82XXhscGetEvents(arg);
+	case HSC_SET_ALARM:
+		if (copy_from_user((void *)&AlarmUser, (void *)arg,
+					sizeof(MotHscAlarmLedSet))) {
+			return -EFAULT;
+		}
+
+		return mot82XXhscSetAlarm(AlarmUser.MasBits, AlarmUser.MasFlag);
+
+	case HSC_GET_ALARM_STAT:
+		return mot82XXhscGetAlarm(arg);
+	case HSC_SET_LED:
+		if (copy_from_user((void *)&AlarmUser, (void *)arg,
+					sizeof(MotHscAlarmLedSet))) {
+			return -EFAULT;
+		}
+
+		return mot82XXhscSetLed(AlarmUser.MasBits, AlarmUser.MasFlag);
+
+	case HSC_GET_LED_STAT:
+		return mot82XXhscGetLed(arg);
+	case HSC_SET_PBAY:
+		return mot82XXhscSetPBay(arg);
+	case HSC_GET_PBAY_STAT:
+		return mot82XXhscGetPBay(arg);
+	case HSC_SET_POWER:
+		return mot82XXhscSetPS(arg);
+	case HSC_GET_POWER_STAT:
+		return mot82XXhscGetPS(arg);
+	case HSC_GET_LOCALHOST:
+		return mot82XXhscGetLocalHost(arg);
+	case HSC_GET_BUS_STATE:
+		return mot82XXhscGetBusState(arg);
+	case HSC_TAKE_BUS:
+		return mot82XXhscTakeBus(arg);
+	case HSC_FREE_BUS:
+		return mot82XXhscFreeBus(arg);
+	case HSC_ALLOW_BUS_TAKE:
+		return mot82XXhscAllowBusTake(arg);
+	case HSC_SET_ENUMMASK:
+		if (copy_from_user((void *)&EnumUser, (void *)arg, sizeof(int))) {
+			return -EFAULT;
+		}
+
+		bus = (EnumUser & 0x3) - 1;
+		flag = (EnumUser & 0x4) >> 2;
+
+		return mot82XXhscSetEnumMask(bus, flag);
+	case HSC_GET_ENUMMASK:
+		return mot82XXhscGetEnumMask(arg);
+	case HSC_GET_ENUM:
+		return mot82XXhscGetEnum(arg);
+	case HSC_GET_NONHOST:
+		return mot82XXhscGetNonHost(arg);
+	case HSC_SET_NONHOST:
+		return mot82XXhscSetNonHost(arg);
+	case HSC_GET_HOST:
+		return mot82XXhscGetHost(arg);
+	case HSC_SET_HOST:
+		return mot82XXhscSetHostst(arg);
+	case HSC_GET_HSC:
+		return mot82XXhscGetHsc(arg);
+	case HSC_SET_HSC:
+		return mot82XXhscSetHsc(arg);
+	default:
+		MotHscStats.BogusCmds++;
+		return -EINVAL;
+	}
+
+	return 0;
+}
+
+/*
+ * Linux driver open function.
+ *
+ * Driver itself does not  do much with this function.  Mostly
+ * exists to allow the kernel code to complete the open.
+ */
+static int
+mot82XXhsc_open(struct inode *inode, struct file *file)
+{
+	MotHscStats.TotalOpens++;
+	MotHscStats.CurOpens++;
+
+	return 0;
+}
+
+/*
+ * Linux driver close function.
+ *
+ * Closeing the driver must ensure the data structures for the 
+ * process have been properly freed.
+ */
+static int
+mot82XXhsc_release(struct inode *inode, struct file *file)
+{
+	HscEventRequesters *TempEvReq;
+	HscEventRequesters *DelEvReq = NULL;
+
+	MotHscStats.CurOpens--;
+
+	/* Check to see if this process is listed with the event
+	 * requesters.
+	 */
+	TempEvReq = MotEventRequestersList;
+
+	if (TempEvReq == NULL) {
+		return 0;
+	}
+
+	if (TempEvReq->Pid == current->pid) {
+		MotEventRequestersList = MotEventRequestersList->Next;
+		DelEvReq = TempEvReq;
+	} else {
+		while (TempEvReq->Next) {
+			if (TempEvReq->Next->Pid == current->pid) {
+				DelEvReq = TempEvReq->Next;
+				TempEvReq->Next = DelEvReq->Next;
+			}
+			if (TempEvReq->Next) {
+				TempEvReq = TempEvReq->Next;
+			}
+		}
+	}
+
+	if (DelEvReq) {
+		DelEvReq->Pid = 0;
+		DelEvReq->Fasyncptr = 0;
+		DelEvReq->Next = MotEventRequestersFreeList;
+		MotEventRequestersFreeList = DelEvReq;
+	}
+
+	return 0;
+}
+
+/*
+ * Linux driver asynchronous notification function.
+ *
+ * Correctly register or deregister from the event notification list.
+ */
+static int
+mot82XXhsc_fasync(int fd, struct file *fp, int on)
+{
+	HscEventRequesters *TempEvReq;
+	HscEventRequesters *DelEvReq = NULL;
+	int		rv;
+
+	if (on) {
+		if (MotEventRequestersFreeList == NULL) {
+			return -ENOSPC;
+		}
+
+		TempEvReq = MotEventRequestersFreeList;
+		MotEventRequestersFreeList = MotEventRequestersFreeList->Next;
+
+		TempEvReq->Pid = current->pid;
+
+		if ((rv = fasync_helper(fd, fp, on, &TempEvReq->Fasyncptr)) < 1) {
+			TempEvReq->Next = MotEventRequestersFreeList;
+			MotEventRequestersFreeList = TempEvReq;
+			return rv;
+		}
+
+		TempEvReq->Next = MotEventRequestersList;
+		MotEventRequestersList = TempEvReq;
+	} else {
+		TempEvReq = MotEventRequestersList;
+		if (TempEvReq->Pid == current->pid) {
+			MotEventRequestersList = MotEventRequestersList->Next;
+			DelEvReq = TempEvReq;
+		} else {
+			while (TempEvReq->Next) {
+				if (TempEvReq->Next->Pid == current->pid) {
+					DelEvReq = TempEvReq->Next;
+					TempEvReq->Next = DelEvReq->Next;
+				}
+				if (TempEvReq->Next) {
+					TempEvReq = TempEvReq->Next;
+				}
+			}
+		}
+
+		if (DelEvReq) {
+			DelEvReq->Pid = 0;
+			DelEvReq->Next = MotEventRequestersFreeList;
+			MotEventRequestersFreeList = DelEvReq;
+
+			if ((rv = fasync_helper(fd, fp, on, &TempEvReq->Fasyncptr)) < 1) {
+				return rv;
+			}
+		} else {
+			return -EPERM;
+		}
+	}
+
+	return 0;
+};
+
+/* Information for each bit in the interrupt register. */
+HscRegInfo MotHscRegInfo[32] = {
+	{(unsigned int *)0, 0, mot82XXhscHandleSlotInt},  /* Bit  0 */
+	{(unsigned int *)0, 1, mot82XXhscHandleSlotInt},  /* Bit  1 */
+	{(unsigned int *)0, 2, mot82XXhscHandleSlotInt},  /* Bit  2 */
+	{(unsigned int *)0, 3, mot82XXhscHandleSlotInt},  /* Bit  3 */
+	{(unsigned int *)0, 4, mot82XXhscHandleSlotInt},  /* Bit  4 */
+	{(unsigned int *)0, 5, mot82XXhscHandleSlotInt},  /* Bit  5 */
+	{(unsigned int *)0, 0, mot82XXhscHandleHostInt},  /* Bit  6 */
+	{(unsigned int *)0, 0, mot82XXhscHandleHSCInt},   /* Bit  7 */
+	{(unsigned int *)0, 1, mot82XXhscHandleHostInt},  /* Bit  8 */
+	{(unsigned int *)0, 1, mot82XXhscHandleHSCInt},   /* Bit  9 */
+	{(unsigned int *)0, 10, mot82XXhscHandleSlotInt}, /* Bit 10 */
+	{(unsigned int *)0, 11, mot82XXhscHandleSlotInt}, /* Bit 11 */
+	{(unsigned int *)0, 12, mot82XXhscHandleSlotInt}, /* Bit 12 */
+	{(unsigned int *)0, 13, mot82XXhscHandleSlotInt}, /* Bit 13 */
+	{(unsigned int *)0, 14, mot82XXhscHandleSlotInt}, /* Bit 14 */
+	{(unsigned int *)0, 15, mot82XXhscHandleSlotInt}, /* Bit 15 */
+	{(unsigned int *)0, 0, mot82XXhscHandlePbayInt},  /* Bit 16 */
+	{(unsigned int *)0, 1, mot82XXhscHandlePbayInt},  /* Bit 17 */
+	{(unsigned int *)0, 2, mot82XXhscHandlePbayInt},  /* Bit 18 */
+	{(unsigned int *)0, 3, mot82XXhscHandlePbayInt},  /* Bit 19 */
+	{(unsigned int *)0, 0, NULL},		          /* Bit 20 */
+	{(unsigned int *)0, 0, NULL},		          /* Bit 21 */
+	{(unsigned int *)0, 0, NULL},		          /* Bit 22 */
+	{(unsigned int *)0, 0, mot82XXhscHandleMaskInt},  /* Bit 23 */
+	{(unsigned int *)0, 0, NULL},		          /* Bit 24 */
+	{(unsigned int *)0, 0, NULL},		          /* Bit 25 */
+	{(unsigned int *)0, 0, mot82XXhscHandlePSInt}, /* Bit 26 */
+	{(unsigned int *)0, 1, mot82XXhscHandlePSInt}, /* Bit 27 */
+	{(unsigned int *)0, 2, mot82XXhscHandlePSInt}, /* Bit 28 */
+	{(unsigned int *)0, 0, mot82XXhscHandleAlarmInt}, /* Bit 29 */
+	{(unsigned int *)0, 0, mot82XXhscHandleBusInt},   /* Bit 30 */
+	{(unsigned int *)0, 1, mot82XXhscHandleBusInt}    /* Bit 31 */
+};
+
+/*
+ * Linux driver interrupt routine.
+ *
+ * At interrupt this routine calls the associated function for each
+ * bit in the interrupt register that is set.
+ */
+static void
+mot82XXhsc_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	unsigned int	status_reg;
+	int		status_bit;
+	HscRegInfo	*int_reg;
+
+	/* Insure the interrupt is for this driver. */
+	if (dev_id != (void *)&mot82XXhsc_fops) {
+		return;
+	}
+
+	/* Check for bogus interrupts */
+	if (!(status_reg = MOTHSC_READREG(IntStatus[0]))) {
+		return;
+	}
+
+	for (status_bit = 0; status_bit < MOTHSC_REG_SIZE; status_bit++) {
+		/* Bit not set - interrupt not present */
+		if (!((1 << status_bit) & status_reg)) {
+			continue;
+		}
+
+		int_reg = MOTHSC_GET_REG_FROM_BIT(status_bit);
+
+		mot82XXhscClrBits(int_reg->Reg, MOTHSC_INT_STATUS);
+
+		MOT_HSC_CALL_INT_HANDLER(status_bit, int_reg);
+	}
+}
+
+/*
+ * Interrupt handling sub routine for the non host slot control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandleSlotInt(volatile unsigned int *reg, int slot)
+{
+	unsigned int Bits;
+	unsigned int OldBits;
+	int loop;
+
+	Bits = MOTHSC_READREG(Slot[slot]) & MOTHSC_SLOTINT;
+	OldBits = MotHscInfo.SlotOldIntBits[slot];
+
+	for (loop = 0; loop < 7; loop++) {
+		if ((Bits & (0x1 << loop)) && !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+						(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.SlotOldIntBits[slot] = Bits;
+}
+
+/*
+ * Interrupt handling sub routine for the host slot control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandleHostInt(volatile unsigned int *reg, int host)
+{
+	unsigned int Bits;
+	unsigned int OldBits;
+	int loop;
+	int slot;
+
+	slot = (host * 2) + 6;
+
+	Bits = MOTHSC_READREG(Slot[slot]) & MOTHSC_HOSTINT;
+	OldBits = MotHscInfo.HostOldIntBits[slot];
+
+	for (loop = 0; loop < 7; loop++) {
+		if ((Bits & (0x1 << loop)) && !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+						(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.HostOldIntBits[slot] = Bits;
+}
+
+/*
+ * Interrupt handling sub routine for the bridge slot control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandleHSCInt(volatile unsigned int *reg, int hsc)
+{
+	unsigned int Bits;
+	unsigned int OldBits;
+	int loop;
+	int slot;
+
+	slot = (hsc * 2) + 7;
+
+	Bits = MOTHSC_READREG(Slot[slot]) & MOTHSC_HSCINT;
+	OldBits = MotHscInfo.HscOldIntBits[slot];
+
+	for (loop = 0; loop < 6; loop++) {
+		if ((Bits & (0x1 << loop)) && !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+						(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.HscOldIntBits[slot] = Bits;
+}
+
+/*
+ * Interrupt handling sub routine for the peripheral bay control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandlePbayInt(volatile unsigned int *reg, int bay)
+{
+	unsigned int Bits;
+	int          loop;
+
+	Bits = MOTHSC_READREG(PBay[bay]);
+	Bits = (Bits & 0x7) + ((Bits & 0x300) >> 5);
+
+	for (loop = 0; loop < 5; loop++) {
+		if ((Bits & (0x1 << loop)) &&
+		    !(MotHscInfo.PBayOldBits[bay] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PBAY1 + bay,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   (MotHscInfo.PBayOldBits[bay] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PBAY1 + bay,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.PBayOldBits[bay] = Bits;
+	return;
+}
+
+/*
+ * Interrupt handling sub routine for the interrupt mask control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandleMaskInt(volatile unsigned int *reg, int unused)
+{
+	int EnumState = MOTHSC_READREG(IntMask);
+	int OldMaskState;
+
+	if (EnumState & MOTHSC_A_STATE) {
+		/* Bus A has generated an ENUM interrupt. */
+		OldMaskState = EnumState & MOTHSC_ENUMA;
+
+		/* Disable ENUM generation on this bus until the ENUM clears. */
+		mot82XXhscClrBits(&MotHscInfo.Regs->IntMask, MOTHSC_ENUMA);
+		if (OldMaskState) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUMMASK,
+				MOT82XXHSC_BUS_A, MOT82XXHSC_EVENT_OFF);
+		}
+
+		/* If the old state was off then this is a new enum. */
+		if (!MotHscInfo.EnumOldState[0]) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUM,
+				MOT82XXHSC_BUS_A, MOT82XXHSC_EVENT_ON);
+			/* IF the PICMG 2.12 is configured then call its
+			 * interrupt routine.
+			 */
+			HsiPlatformEnumHandler(0, NULL, NULL);
+		}
+	}
+
+	if (EnumState & MOTHSC_B_STATE) {
+		/* Bus B has generated an ENUM interrupt. */
+		OldMaskState = EnumState & MOTHSC_ENUMB;
+
+		/* Disable ENUM generation on this bus until the ENUM clears. */
+		mot82XXhscClrBits(&MotHscInfo.Regs->IntMask, MOTHSC_ENUMB);
+		if (OldMaskState) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUMMASK,
+				MOT82XXHSC_BUS_B, MOT82XXHSC_EVENT_OFF);
+		}
+
+		/* If the old state was off then this is a new enum. */
+		if (!MotHscInfo.EnumOldState[1]) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUM,
+				MOT82XXHSC_BUS_B, MOT82XXHSC_EVENT_ON);
+			/* IF the PICMG 2.12 is configured then call its
+			 * interrupt routine.
+			 */
+			HsiPlatformEnumHandler(0, NULL, NULL);
+		}
+	}
+
+	/* Update the history information. */
+	MotHscInfo.EnumOldState[0] = MOTHSC_READREG(IntMask) & MOTHSC_A_STATE;
+	MotHscInfo.EnumOldState[1] = MOTHSC_READREG(IntMask) & MOTHSC_B_STATE;
+}
+
+/*
+ * Interrupt handling sub routine for the power supply control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandlePSInt(volatile unsigned int *reg, int supply)
+{
+	unsigned int Bits;
+	int          loop;
+
+	Bits = MOTHSC_READREG(Ps[supply]);
+	Bits = (Bits & 0x1f) + ((Bits & 0x7f00) >> 3);
+
+	for (loop = 0; loop < 12; loop++) {
+		if ((Bits & (0x1 << loop)) &&
+		    !(MotHscInfo.PowerOldBits[supply] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PS1 + supply,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   (MotHscInfo.PowerOldBits[supply] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PS1 + supply,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.PowerOldBits[supply] = Bits;
+}
+
+/*
+ * Interrupt handling sub routine for the chassis alarm control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandleAlarmInt(volatile unsigned int *reg, int unused)
+{
+	return;
+}
+
+/*
+ * Interrupt handling sub routine for the bus control
+ * registers.  Routine will generate an event for each bit changed that
+ * can result in an interrupt being posted.
+ */
+static void
+mot82XXhscHandleBusInt(volatile unsigned int *reg, int bus)
+{
+	unsigned int check_val1;
+	unsigned int check_val2 = (MotHscInfo.LastBusControl[bus] &
+				(MOTHSC_XFR_CTL1 | MOTHSC_XFR_CTL2 |
+				MOTHSC_XFR_STS1 | MOTHSC_XFR_STS2)) >> 1;
+
+	/* Is the other side requesting the bus */
+	if (MOTHSC_READREG(BusControl[bus]) & MOTHSC_XFR_STS1) {
+		/* Does the other side now posses the bus. */
+		if ((MOTHSC_READREG(BusControl[bus]) & MOTHSC_XFR_STS2) &&
+		    (check_val2 == HSC_STATE_MINE)) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_BUS_RELEASED,
+						bus + MOT82XXHSC_BUS_A, 0);
+			MotHscInfo.BusTakeoverAllowed[bus] = 0;
+			MotHscInfo.LastBusControl[bus] =
+					MOTHSC_READREG(BusControl[bus]);
+			motCpciSetDomainTakeover(bus);
+			return;
+		}
+
+		/* If we have allowed the other side to take over the bus
+		 * then let him have it.  Else send an event to use software
+		 * requesting the bus. */
+		if (MotHscInfo.BusTakeoverAllowed[bus]) {
+			/* Grant the takeover */
+			mot82XXhscClrBits(&MotHscInfo.Regs->BusControl[bus],
+							MOTHSC_XFR_CTL1);
+		} else {
+			/* Send event indicating take over request */
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_BUS_TAKE_REQ,
+						bus + MOT82XXHSC_BUS_A, 0);
+		}
+
+		MotHscInfo.LastBusControl[bus] =
+					MOTHSC_READREG(BusControl[bus]);
+		return;
+	}
+
+	check_val1 = (MOTHSC_READREG(BusControl[bus]) &
+				(MOTHSC_XFR_CTL1 | MOTHSC_XFR_CTL2 |
+				MOTHSC_XFR_STS1 | MOTHSC_XFR_STS2)) >> 1;
+	check_val2 = (MotHscInfo.LastBusControl[bus] &
+				(MOTHSC_XFR_CTL1 | MOTHSC_XFR_CTL2 |
+				MOTHSC_XFR_STS1 | MOTHSC_XFR_STS2)) >> 1;
+
+	/* Check to see if the transitions have competed. */
+	switch (check_val1) {
+	case HSC_STATE_MINE:
+		switch(check_val2) {
+		case HSC_STATE_OTHER:
+		case HSC_STATE_FREE:
+			/* Notify event the bus take over has compeleted. */
+			del_timer(&mot82XXhscTakeTimeOut);
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_BUS_TAKE_DONE,
+						bus + MOT82XXHSC_BUS_A, 0);
+			break;
+		}
+		break;
+	default:
+		switch(check_val2) {
+		case HSC_STATE_MINE:
+		case HSC_STATE_OTHER:
+			/* Notify event the other host has taken the bus. */
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_BUS_RELEASED,
+						bus + MOT82XXHSC_BUS_A, 0);
+			MotHscInfo.BusTakeoverAllowed[bus] = 0;
+			break;
+		}
+		break;
+	}
+	MotHscInfo.LastBusControl[bus] = MOTHSC_READREG(BusControl[bus]);
+	return;
+}
+
+/*
+ * Fill in the register pointers in the driver instance information.  Since
+ * the registers exist on ioremaped space this cannot be done at compile time.
+ */
+static void
+mot82XXhscMapIntBitsToRegisters(void)
+{
+
+	MotHscRegInfo[0].Reg = &MotHscInfo.Regs->Slot[0];	   /* Bit 0  */
+	MotHscRegInfo[1].Reg = &MotHscInfo.Regs->Slot[1];	   /* Bit 1  */
+	MotHscRegInfo[2].Reg = &MotHscInfo.Regs->Slot[2];	   /* Bit 2  */
+	MotHscRegInfo[3].Reg = &MotHscInfo.Regs->Slot[3];	   /* Bit 3  */
+	MotHscRegInfo[4].Reg = &MotHscInfo.Regs->Slot[4];	   /* Bit 4  */
+	MotHscRegInfo[5].Reg = &MotHscInfo.Regs->Slot[5];	   /* Bit 5  */
+	MotHscRegInfo[6].Reg = &MotHscInfo.Regs->Slot[6];	   /* Bit 6  */
+	MotHscRegInfo[7].Reg = &MotHscInfo.Regs->Slot[7];	   /* Bit 7  */
+	MotHscRegInfo[8].Reg = &MotHscInfo.Regs->Slot[8];	   /* Bit 8  */
+	MotHscRegInfo[9].Reg = &MotHscInfo.Regs->Slot[9];	   /* Bit 9  */
+	MotHscRegInfo[10].Reg = &MotHscInfo.Regs->Slot[10];	   /* Bit 10 */
+	MotHscRegInfo[11].Reg = &MotHscInfo.Regs->Slot[11];	   /* Bit 11 */
+	MotHscRegInfo[12].Reg = &MotHscInfo.Regs->Slot[12];	   /* Bit 12 */
+	MotHscRegInfo[13].Reg = &MotHscInfo.Regs->Slot[13];	   /* Bit 13 */
+	MotHscRegInfo[14].Reg = &MotHscInfo.Regs->Slot[14];	   /* Bit 14 */
+	MotHscRegInfo[15].Reg = &MotHscInfo.Regs->Slot[15];	   /* Bit 15 */
+	MotHscRegInfo[16].Reg = &MotHscInfo.Regs->PBay[0];	   /* Bit 16 */
+	MotHscRegInfo[17].Reg = &MotHscInfo.Regs->PBay[1];	   /* Bit 17 */
+	MotHscRegInfo[18].Reg = &MotHscInfo.Regs->PBay[2];	   /* Bit 18 */
+	MotHscRegInfo[19].Reg = &MotHscInfo.Regs->PBay[3];	   /* Bit 19 */
+	MotHscRegInfo[23].Reg = &MotHscInfo.Regs->IntMask;	   /* Bit 23 */
+	MotHscRegInfo[26].Reg = &MotHscInfo.Regs->Ps[0];	   /* Bit 26 */
+	MotHscRegInfo[27].Reg = &MotHscInfo.Regs->Ps[1];	   /* Bit 27 */
+	MotHscRegInfo[28].Reg = &MotHscInfo.Regs->Ps[2];	   /* Bit 28 */
+	MotHscRegInfo[29].Reg = &MotHscInfo.Regs->Alarm;	   /* Bit 29 */
+	MotHscRegInfo[30].Reg = &MotHscInfo.Regs->BusControl[0];  /* Bit 30 */
+	MotHscRegInfo[31].Reg = &MotHscInfo.Regs->BusControl[1];  /* Bit 31 */
+}
+
+/*
+ * Ioctl sub function to retrieve hot swap controller register 
+ * contents.  Helps with debug.
+ */
+static int
+mot82XXhscGetRegs(unsigned long arg)
+{
+	MotHscRegisters ToUser;
+	int	loop;
+
+	for (loop = 0; loop < MOTHSC_NUM_SLOTS; loop++) {
+		ToUser.MhrSlot[loop] = MOTHSC_READREG(Slot[loop]);
+	}
+
+	for (loop = 0; loop < MOTHSC_NUM_SLOTS; loop++) {
+		ToUser.MhrPower[loop] = MOTHSC_READREG(Ps[loop]);
+	}
+
+	for (loop = 0; loop < MOTHSC_NUM_PBAY; loop++) {
+		ToUser.MhrPBay[loop] = MOTHSC_READREG(PBay[loop]);
+	}
+
+	ToUser.MhrIntStatMask = MOTHSC_READREG(IntStatMask);
+
+	for (loop = 0; loop < MOTHSC_NUM_INTSTAT; loop++) {
+		ToUser.MhrIntStatus[loop] = MOTHSC_READREG(IntStatus[loop]);
+	}
+
+	for (loop = 0; loop < MOTHSC_NUM_BUS; loop++) {
+		ToUser.MhrBusControl[loop] = MOTHSC_READREG(BusControl[loop]);
+	}
+
+	ToUser.MhrEEprom = MOTHSC_READREG(EEprom);
+	ToUser.MhrSysLed = MOTHSC_READREG(SysLed);
+	ToUser.MhrAlarm = MOTHSC_READREG(Alarm);
+	ToUser.MhrIntMask = MOTHSC_READREG(IntMask);
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(MotHscRegisters));
+}
+
+/*
+ * Retrieve event information sub ioctl.
+ */
+static int
+mot82XXhscGetEvents(unsigned long arg)
+{
+	MotHscEvents ToUser;
+	HscEventRequesters *Requester = MotEventRequestersList;
+	HscMessage *Message;
+	HscMessage *OldMessage;
+
+	/* Find the reqestors id from the list of valid requestors. */
+	while(Requester) {
+		if (current->pid != Requester->Pid) {
+			Requester = Requester->Next;
+			continue;
+		}
+
+		Message = Requester->Head;
+		ToUser.Count = 0;
+
+		/* For each message up to max, fill in the return info. */
+		while (Message && (ToUser.Count < MOTHSC_EVENTS_MAX)) {
+			ToUser.Events[ToUser.Count].Event = Message->Event;
+			ToUser.Events[ToUser.Count].Unit = Message->Unit;
+			ToUser.Events[ToUser.Count].Val = Message->Val;
+			ToUser.Count++;
+
+			OldMessage = Message;
+			Message = Message->Next;
+			mot82XXhscFreeMessage(OldMessage);
+		}
+
+		if ((Requester->Head = Message) == NULL) {
+			Requester->Tail = NULL;
+		}
+
+		return copy_to_user((void *)arg, &ToUser, sizeof(MotHscEvents));
+	}
+
+	return -EIO;
+}
+
+/*
+ * Sub ioclt functionality to control the alarm register settings.
+ */
+static int
+mot82XXhscSetAlarm(unsigned int bits, unsigned int flag)
+{
+	unsigned int	Bits;
+	unsigned int	OldBits;
+	int		loop;
+
+	if (bits & ~MOT82XXHSC_ALARM_MASK) {
+		return -EINVAL;
+	}
+
+	Bits = bits << 8;
+	OldBits = MOTHSC_READREG(Alarm) >> 8;
+
+	if (flag) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->Alarm, Bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Alarm, Bits);
+	}
+
+	Bits = MOTHSC_READREG(Alarm) >> 8;
+
+	/* Check register for any bit changes and return resulting events. */
+	for (loop = 0; loop < 4; loop++) {
+		if ((Bits & (0x1 << loop)) &&
+		    !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ALARM,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   (OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ALARM,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Sub ioctl to return current alarm bit settings.
+ */
+static int
+mot82XXhscGetAlarm(unsigned long arg)
+{
+	int ToUser;
+
+	ToUser = (MOTHSC_READREG(Alarm) >> 8) & MOT82XXHSC_ALARM_MASK;
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Ioctl sub function to set chassis LED control bits.
+ */
+static int
+mot82XXhscSetLed(unsigned int bits, int unsigned flag)
+{
+	unsigned int	Bits;
+	unsigned int	OldBits;
+	int		loop;
+
+	if (bits & ~MOT82XXHSC_LED_MASK) {
+		return -EINVAL;
+	}
+
+	Bits = bits << 8;
+	OldBits = MOTHSC_READREG(SysLed) >> 8;
+
+	if (flag) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->SysLed, bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->SysLed, bits);
+	}
+
+	Bits = MOTHSC_READREG(SysLed) >> 8;
+
+	for (loop = 0; loop < 4; loop++) {
+		if ((Bits & (0x1 << loop)) &&
+		    !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_LED,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   (OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_LED,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	return 0;
+}
+
+/*
+ * Sub ioctl function to return the current chassis LED settings. 
+ */
+static int
+mot82XXhscGetLed(unsigned long arg)
+{
+	int ToUser;
+
+	ToUser = (MOTHSC_READREG(SysLed) >> 8) & MOT82XXHSC_LED_MASK;
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Sub ioctl to set peripheral bay controls.
+ */
+static int
+mot82XXhscSetPBay(unsigned long arg)
+{
+	MotHscPBayInfo	FromUser;
+	unsigned int	Bits;
+	int		loop;
+	int		bay;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg,
+					sizeof(MotHscPBayInfo))) {
+		return -EFAULT;
+	}
+
+	if (FromUser.MpbiBits & ~MOT82XXHSC_PBAY_MASK) {
+		return -EINVAL;
+	}
+
+	bay = FromUser.MpbiBay - 1;
+
+	if ((bay < 0) || (bay > 3)) {
+		return -EINVAL;
+	}
+
+	Bits = (FromUser.MpbiBits & 0x7) + ((FromUser.MpbiBits & 0x18) << 5);
+
+	if (FromUser.MpbiFlag) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->PBay[bay], Bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->PBay[bay], Bits);
+	}
+
+	Bits = MOTHSC_READREG(PBay[bay]);
+	Bits = (Bits & 0x7) + ((Bits & 0x300) >> 5);
+
+	for (loop = 0; loop < 5; loop++) {
+		if ((Bits & (0x1 << loop)) &&
+		    !(MotHscInfo.PBayOldBits[bay] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PBAY1 + bay,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   (MotHscInfo.PBayOldBits[bay] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PBAY1 + bay,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.PBayOldBits[bay] = Bits;
+	return 0;
+}
+
+/*
+ * Ioctl sub function to return the setting for the peripheral bay.
+ */
+static int
+mot82XXhscGetPBay(unsigned long arg)
+{
+	int ToUser;
+	int FromUser;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	if ((FromUser < 1) || (FromUser > 4)) {
+		return -EINVAL;
+	}
+	
+	ToUser = MOTHSC_READREG(PBay[FromUser-1]);
+	ToUser = (ToUser & 0x7) | ((ToUser & 0x300) >> 5);
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Sub ioctl to control power supply settings.
+ */
+static int
+mot82XXhscSetPS(unsigned long arg)
+{
+	MotHscPsInfo	FromUser;
+	unsigned int	Bits;
+	int		loop;
+	int		supply;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg,
+					sizeof(MotHscPsInfo))) {
+		return -EFAULT;
+	}
+
+	if (FromUser.MpsiBits & ~MOT82XXHSC_PS_MASK) {
+		return -EINVAL;
+	}
+
+	supply = FromUser.MpsiPS - 1;
+
+	if ((supply < 0) || (supply > 2)) {
+		return -EINVAL;
+	}
+
+	Bits = (FromUser.MpsiBits & 0x1f) +
+				((FromUser.MpsiBits & 0xfe0) << 3);
+
+	if (FromUser.MpsiFlag) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->Ps[supply], Bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Ps[supply], Bits);
+	}
+
+	Bits = MOTHSC_READREG(Ps[supply]);
+	Bits = (Bits & 0x1f) + ((Bits & 0x7f00) >> 3);
+
+	for (loop = 0; loop < 12; loop++) {
+		if ((Bits & (0x1 << loop)) &&
+		    !(MotHscInfo.PowerOldBits[supply] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PS1 + supply,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   (MotHscInfo.PowerOldBits[supply] & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_PS1 + supply,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.PowerOldBits[supply] = Bits;
+	return 0;
+}
+
+/*
+ * Ioctl sub function to return power supply control settings.
+ */
+static int
+mot82XXhscGetPS(unsigned long arg)
+{
+	int ToUser;
+	int FromUser;
+	unsigned int Bits;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	if ((FromUser < 1) || (FromUser > 3)) {
+		return -EINVAL;
+	}
+	
+	Bits = MOTHSC_READREG(Ps[FromUser-1]);
+	ToUser = (Bits & 0x1f) | ((Bits & 0x7f00) >> 3);
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Return idication of which host (A or B) the software is executing on.
+ */
+static int
+mot82XXhscGetLocalHost(unsigned long arg)
+{
+	return copy_to_user((void *)arg, &MotHscInfo.Host, sizeof(int));
+}
+
+/*
+ * Sub ioctl to return the bus state.
+ */
+static int
+mot82XXhscGetBusState(unsigned long arg)
+{
+	unsigned int FromUser;
+	unsigned int ToUser;
+	int state;
+	int bus;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	bus = FromUser - 1;
+	state = (MOTHSC_READREG(BusControl[bus]) & 0x1e) >> 1;
+
+	switch (state) {
+	case HSC_STATE_FREE:
+		ToUser = MOT82XXHSC_BUS_FREE;
+		break;
+	case HSC_STATE_OTHER:
+		ToUser = MOT82XXHSC_BUS_OTHER;
+		break;
+	case HSC_STATE_REQUESTED:
+		ToUser = MOT82XXHSC_BUS_REQUESTED;
+		break;
+	case HSC_STATE_TRAN_STRT:
+		ToUser = MOT82XXHSC_BUS_TRAN_START;
+		break;
+	case HSC_STATE_STOPED:
+		ToUser = MOT82XXHSC_BUS_STOPED;
+		break;
+	case HSC_STATE_TRAN_ACK:
+		ToUser = MOT82XXHSC_BUS_TRAN_ACK;
+		break;
+	case HSC_STATE_ENABLE:
+		ToUser = MOT82XXHSC_BUS_ENABLE;
+		break;
+	case HSC_STATE_TRAN_DONE:
+		ToUser = MOT82XXHSC_BUS_TRAN_DONE;
+		break;
+	case HSC_STATE_MINE:
+		ToUser = MOT82XXHSC_BUS_MINE;
+		break;
+	}
+
+	if (MotHscInfo.BusTakeoverAllowed[bus]) {
+		ToUser |= MOT82XXHSC_BUS_ALLOWTO;
+	}
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Ioctl sub function to take over the specified bus.
+ */
+static int
+mot82XXhscTakeBus(unsigned long arg)
+{
+	unsigned int FromUser;
+	int bus;
+	int timeout;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	bus = (FromUser & MOT82XXHSC_BUS_MASK) - 1;
+
+	if ((bus < 0) || (bus > 1)) {
+		return -EINVAL;
+	}
+
+	timeout = (FromUser & MOT82XXHSC_BUS_TIMEO_MASK) >> 16;
+
+	return mot82XXhscAttachBus(bus, timeout);
+}
+
+/*
+ * Ioctl sub function to free the specified bus.
+ */
+static int
+mot82XXhscFreeBus(unsigned long arg)
+{
+	unsigned int FromUser;
+	int bus;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	bus = (FromUser & MOT82XXHSC_BUS_MASK) - 1;
+
+	if ((bus < 0) || (bus > 1)) {
+		return -EINVAL;
+	}
+
+	return mot82XXhscReleaseBus(bus);
+}
+
+/*
+ * Ioctl sub function to allow the other host to take the bus.
+ */
+static int
+mot82XXhscAllowBusTake(unsigned long arg)
+{
+	unsigned int FromUser;
+	int bus;
+	int flag;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	bus = (FromUser & MOT82XXHSC_BUS_MASK) - 1;
+	flag = FromUser & MOT82XXHSC_BUS_ALLOWTO;
+
+	if (!(MotHscInfo.LastBusControl[bus] &
+				(MOTHSC_XFR_CTL1 | MOTHSC_XFR_CTL2))) {
+		/* Cannot grant allow a a bus thet is not owned by this
+		 * processor. */
+		return -EINVAL;
+
+	}
+
+	MotHscInfo.BusTakeoverAllowed[bus] = flag;
+
+	if (!flag) {
+		mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_BUS_DISALLOW,
+						bus + MOT82XXHSC_BUS_A, 0);
+		return 0;
+	}
+
+	mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_BUS_ALLOW,
+						bus + MOT82XXHSC_BUS_A, 0);
+
+	/* Take over now allowed so check to see if take over has been
+	 * requested.
+	 */
+	if (MOTHSC_READREG(BusControl[bus]) & MOTHSC_XFR_STS1) {
+		mot82XXhscClrBits(&MotHscInfo.Regs->BusControl[bus],
+							MOTHSC_XFR_CTL1);
+		MotHscInfo.LastBusControl[bus] =
+					MOTHSC_READREG(BusControl[bus]);
+	}
+	return 0;
+}
+
+/*
+ * Sub ioctl to get the current enum bask setting for the specified bus.
+ */
+static int
+mot82XXhscGetEnumMask(unsigned long arg)
+{
+	unsigned int FromUser;
+	unsigned int ToUser;
+	int bus;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	bus = (FromUser & 0x3) - 1;
+
+	if ((bus < 0) || (bus > 1)) {
+		return -EINVAL;
+	}
+
+	if (MOTHSC_READREG(IntMask) & (MOTHSC_ENUMA << bus)) {
+		ToUser = 1;
+	} else {
+		ToUser = 0;
+	}
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Sbu ioctl to set the enum bask for the specified bus.
+ */
+int
+mot82XXhscSetEnumMask(int bus, int flag)
+{
+	int Stat;
+	int OldStat;
+	unsigned long flags;
+
+	if ((bus < 0) || (bus > 1)) {
+		return -EINVAL;
+	}
+
+	save_flags(flags);
+	cli();
+
+	OldStat = MOTHSC_READREG(IntMask) & (MOTHSC_ENUMA << bus);
+
+	if (flag) {
+		MotHscInfo.EnumEnabled[bus] = 1;
+		mot82XXhscSetBits(&MotHscInfo.Regs->IntMask,
+							(MOTHSC_ENUMA << bus));
+		/* Ensure that an enum event will be transmited if an enum
+		 * exists.  */
+		if (MotHscInfo.EnumOldState[bus]) {
+			MotHscInfo.EnumOldState[bus] = 0;
+		
+			/* If the enum mask has changed the send event up. */
+			if (!OldStat) {
+				mot82XXhscSendEvent(0,
+					MOT82XXHSC_EVENT_ENUM,
+					MOT82XXHSC_BUS_A + bus,
+					MOT82XXHSC_EVENT_OFF);
+			}
+		}
+	} else {
+		MotHscInfo.EnumEnabled[bus] = 0;
+		mot82XXhscClrBits(&MotHscInfo.Regs->IntMask,
+							(MOTHSC_ENUMA << bus));
+	}
+
+	Stat = MOTHSC_READREG(IntMask) & (MOTHSC_ENUMA << bus);
+
+	if (Stat && !OldStat) {
+		mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUMMASK,
+				MOT82XXHSC_BUS_A + bus, MOT82XXHSC_EVENT_ON);
+	} else if (!Stat && OldStat) {
+		mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUMMASK,
+				MOT82XXHSC_BUS_A + bus, MOT82XXHSC_EVENT_OFF);
+	}
+
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * Sub ioctl to return current enum status for the specified bus.
+ */
+static int
+mot82XXhscGetEnum(unsigned long arg)
+{
+	unsigned int FromUser;
+	unsigned int ToUser;
+	int bus;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	bus = (FromUser & 0x3) - 1;
+
+	if ((bus < 0) || (bus > 1)) {
+		return -EINVAL;
+	}
+
+	if (MOTHSC_READREG(IntMask) & (MOTHSC_A_STATE << bus)) {
+		ToUser = 1;
+	} else {
+		ToUser = 0;
+	}
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Sub ioctl to get the current status bits for non host slot controls.
+ */
+static int
+mot82XXhscGetNonHost(unsigned long arg)
+{
+	unsigned int FromUser;
+	unsigned int ToUser;
+	int slot;
+	int bits;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	slot = FromUser - 1;
+
+	if ((slot < 0) || (slot > 15) || ((slot > 5) && (slot < 10))) {
+		return -EINVAL;
+	}
+
+	bits = MOTHSC_READREG(Slot[slot]);
+
+	ToUser = (bits & 0x7f) + ((bits & 0x700) >> 1) +
+					((bits & MOTHSC_ACTIVE) >> 14);
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Sub ioctl to set the current status bits for non host slot controls.
+ */
+static int
+mot82XXhscSetNonHost(unsigned long arg)
+{
+	MotHscSlotInfo	FromUser;
+	unsigned int	Bits;
+	unsigned int	OldBits;
+	unsigned long	flags;
+	int		loop;
+	int		slot;
+	int		bus;
+	int		OldEnumVal = 0;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg,
+					sizeof(MotHscSlotInfo))) {
+		return -EFAULT;
+	}
+
+	if (FromUser.MsiBits & ~MOT82XXHSC_NH_MASK) {
+		return -EINVAL;
+	}
+
+	slot = FromUser.MsiSlot - 1;
+
+	if ((slot >= 0) && (slot < 6)) {
+		bus = 0;
+	} else if ((slot > 9) && (slot < 16)) {
+		bus = 1;
+	} else {
+		return -EINVAL;
+	}
+
+	Bits = (FromUser.MsiBits & 0x7f) + ((FromUser.MsiBits & 0x380) << 1);
+
+	if ((Bits & MOTHSC_CONNECT) && !FromUser.MsiFlag) {
+		/* We are turning of connect so indicate if we need to check
+		 * if ENUM cleare. */
+		OldEnumVal = MOTHSC_READREG(IntMask) & (MOTHSC_A_STATE << bus);
+	}
+
+	save_flags(flags);
+	cli();
+
+	if (FromUser.MsiFlag) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->Slot[slot], Bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Slot[slot], Bits);
+	}
+
+	Bits = MOTHSC_READREG(Slot[slot]) & ~MOTHSC_SLOTINT;
+	Bits = (Bits & 0x7f) + ((Bits & MOTHSC_ACTIVE) >> 14) +
+						 ((Bits & 0x700) >> 1);
+	OldBits = MotHscInfo.SlotOldBits[slot];
+
+	/* Return events for changed no interrup controled bits. */
+	for (loop = 0; loop < 11; loop++) {
+		if ((Bits & (0x1 << loop)) && !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   			(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + slot,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.SlotOldBits[slot] = Bits;
+
+	/* If enum was set see if it has been cleared */
+	if (OldEnumVal && !(MOTHSC_READREG(IntMask) & (MOTHSC_A_STATE << bus ))) {
+		mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUM,
+				MOT82XXHSC_BUS_A + bus, MOT82XXHSC_EVENT_OFF);
+		MotHscInfo.EnumOldState[bus] = 0;
+
+		if (MotHscInfo.EnumEnabled[bus]) {
+			mot82XXhscSetBits(&MotHscInfo.Regs->IntMask, MOTHSC_ENUMA+bus);
+
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_ENUMMASK,
+				MOT82XXHSC_BUS_A + bus, MOT82XXHSC_EVENT_ON);
+		}
+	}
+
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * Sub ioctl to get the current status bits for host slot controls.
+ */
+static int
+mot82XXhscGetHost(unsigned long arg)
+{
+	unsigned int FromUser;
+	unsigned int ToUser;
+	int host;
+	int bits;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	host = (FromUser & 0x3) - 1;
+
+	if ((host < 0) || (host > 1)) {
+		return -ENODEV;
+	}
+
+	host = (host * 2) + 6;
+
+	bits = MOTHSC_READREG(Slot[host]);
+
+	ToUser = (bits & 0x7f) + ((bits & 0x700) >> 1) +
+					((bits & MOTHSC_ACTIVE) >> 14);
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Sub ioctl to set the current status bits for host slot controls.
+ */
+static int
+mot82XXhscSetHostst(unsigned long arg)
+{
+	MotHscSlotInfo	FromUser;
+	unsigned int	Bits;
+	unsigned int	OldBits;
+	unsigned long	flags;
+	int		loop;
+	int		host;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg,
+					sizeof(MotHscSlotInfo))) {
+		return -EFAULT;
+	}
+
+	if (FromUser.MsiBits & ~MOT82XXHSC_HOST_MASK) {
+		return -EINVAL;
+	}
+
+	host = (FromUser.MsiSlot & 0x3) - 1;
+
+	if ((host < 0) || (host > 1)) {
+		return -ENODEV;
+	}
+
+	host = (host * 2) + 6;
+
+	Bits = (FromUser.MsiBits & 0x7f) + ((FromUser.MsiBits & 0x380) << 1);
+
+	save_flags(flags);
+	cli();
+
+	if (FromUser.MsiFlag) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->Slot[host], Bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Slot[host], Bits);
+	}
+
+	Bits = MOTHSC_READREG(Slot[host]) & ~MOTHSC_HOSTINT;
+	Bits = (Bits & 0x7f) + ((Bits & 0x700) >> 1) +
+						((Bits & MOTHSC_ACTIVE) >> 14);
+
+	OldBits = MotHscInfo.HostOldBits[host];
+
+	for (loop = 0; loop < 11; loop++) {
+		if ((Bits & (0x1 << loop)) && !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + host,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   			(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + host,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.HostOldBits[host] = Bits;
+
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * Sub ioctl to get the current status bits for bridge slot controls.
+ */
+static int
+mot82XXhscGetHsc(unsigned long arg)
+{
+	unsigned int FromUser;
+	unsigned int ToUser;
+	int hsc;
+	int bits;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg, sizeof(int))) {
+		return -EFAULT;
+	}
+
+	hsc = (FromUser & 0x3) - 1;
+
+	if ((hsc < 0) || (hsc > 1)) {
+		return -ENODEV;
+	}
+
+	hsc = (hsc * 2) + 7;
+
+	bits = MOTHSC_READREG(Slot[hsc]);
+
+	ToUser = (bits & 0x7f) + ((bits & 0x700) >> 1) +
+					((bits & MOTHSC_ACTIVE) >> 14);
+
+	return copy_to_user((void *)arg, &ToUser, sizeof(int));
+}
+
+/*
+ * Sub ioctl to get the current status bits for bridge slot controls.
+ */
+static int
+mot82XXhscSetHsc(unsigned long arg)
+{
+	MotHscSlotInfo	FromUser;
+	unsigned int	Bits;
+	unsigned int	OldBits;
+	unsigned long	flags;
+	int		loop;
+	int		hsc;
+
+	if (copy_from_user((void *)&FromUser, (void *)arg,
+					sizeof(MotHscSlotInfo))) {
+		return -EFAULT;
+	}
+
+	if (FromUser.MsiBits & ~MOT82XXHSC_HSC_MASK) {
+		return -EINVAL;
+	}
+
+	hsc = (FromUser.MsiSlot & 0x3) - 1;
+
+	if ((hsc < 0) || (hsc > 1)) {
+		return -ENODEV;
+	}
+
+	hsc = (hsc * 2) + 7;
+
+	Bits = (FromUser.MsiBits & 0x7f) + ((FromUser.MsiBits & 0x380) << 1);
+
+	save_flags(flags);
+	cli();
+
+	if (FromUser.MsiFlag) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->Slot[hsc], Bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Slot[hsc], Bits);
+	}
+
+	Bits = MOTHSC_READREG(Slot[hsc]) & ~MOTHSC_HSCINT;
+	Bits = (Bits & 0x7f) + ((Bits & 0x700) >> 1) +
+					((Bits & MOTHSC_ACTIVE) >> 14);
+
+	OldBits = MotHscInfo.HscOldBits[hsc];
+
+	for (loop = 0; loop < 11; loop++) {
+		if ((Bits & (0x1 << loop)) && !(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + hsc,
+					0x1 << loop, MOT82XXHSC_EVENT_ON);
+		} else if (!(Bits & (0x1 << loop)) &&
+			   			(OldBits & (0x1 << loop))) {
+			mot82XXhscSendEvent(0, MOT82XXHSC_EVENT_SLOT1 + hsc,
+					0x1 << loop, MOT82XXHSC_EVENT_OFF);
+		}
+	}
+
+	MotHscInfo.HscOldBits[hsc] = Bits;
+
+	restore_flags(flags);
+	return 0;
+}
+
+/*
+ * Clear the bits specified by the bit mask in the requested register.
+ */
+static void
+mot82XXhscClrBits(volatile unsigned int *reg, unsigned int bits)
+{
+	*reg = cpu_to_le32(bits | MOTHSC_CMD_CLEAR);
+	udelay(10);
+}
+
+/*
+ * Set the bits specified by the bit mask in the requested register.
+ */
+static void
+mot82XXhscSetBits(volatile unsigned int *reg, unsigned int bits)
+{
+	*reg = cpu_to_le32(bits | MOTHSC_CMD_SET);
+	udelay(10);
+}
+
+/*
+ * Sub function of take over routine to turn on interrupts to the
+ * non host slots and recored the history information.
+ */
+void
+mot82XXhscSlotOn(int bus)
+{
+	unsigned int Bits;
+	int startslot = 0;
+	int slot;
+
+	if (bus) {
+		startslot = 10;
+	}
+
+	for (slot = startslot; slot < startslot + 6; slot++) {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Slot[slot],
+							MOTHSC_INTC_ENABLE);
+		mot82XXhscSetBits(&MotHscInfo.Regs->Slot[slot],
+							MOTHSC_INTA_ENABLE);
+		Bits = MOTHSC_READREG(Slot[slot]) & ~MOTHSC_SLOTINT;
+		MotHscInfo.SlotOldBits[slot] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & ~MOTHSC_SLOTINT;
+		MotHscInfo.SlotOldIntBits[slot] = ((Bits & 0x7f) +
+				((Bits & MOTHSC_ACTIVE) >> 14) +
+				((Bits & 0x700) >> 1)) & MOTHSC_SLOTINT;
+	}
+
+	return;
+}
+
+/*
+ * Time out function used for bus takeover.  This function is scheduled to
+ * run at the time out value.  At time out it completes the take over whether
+ * the other host has allowed it or not.  This function is also called
+ * directly by this host when the other host has allowed takeover.
+ */
+void
+mot82XXhscTakeTimeOutFunc(unsigned long bus)
+{
+	/* Seting XFR_CTL1 enables all controls */
+	mot82XXhscSetBits(&MotHscInfo.Regs->BusControl[bus], MOTHSC_XFR_CTL2);
+
+	MotHscInfo.LastBusControl[bus] = MOTHSC_READREG(BusControl[bus]);
+
+	/* If we allocated the A bus then enable interrupts for the Alarms */
+	if (!bus) {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Alarm, MOTHSC_INTC_ENABLE);
+		mot82XXhscSetBits(&MotHscInfo.Regs->Alarm, MOTHSC_INTA_ENABLE);
+	}
+
+	/* Turn on interrupts to all the slots on this bus */
+	mot82XXhscSlotOn(bus);
+
+	return;
+}
+
+/*
+ * Functionality to take over the specified bus.
+ */
+static int
+mot82XXhscAttachBus(int bus, int timeout)
+{
+	/* Set this bus to generate interrupts on INT A */
+	mot82XXhscClrBits(&MotHscInfo.Regs->BusControl[bus], MOTHSC_INTC_ENABLE);
+	mot82XXhscSetBits(&MotHscInfo.Regs->BusControl[bus], MOTHSC_INTA_ENABLE);
+
+	/* First set XFR_CTL1 to request bus.2 */
+	mot82XXhscSetBits(&MotHscInfo.Regs->BusControl[bus], MOTHSC_XFR_CTL1);
+
+	/* if timeout value not zero then wait that long for the other host
+	 * to give up the bus.  At timeout force the takeover. 
+	 */
+	if ((timeout != 0) &&
+			(MOTHSC_READREG(BusControl[bus]) & MOTHSC_XFR_STS1)) {
+		mot82XXhscTakeTimeOut.data = (unsigned long)bus;
+		mot82XXhscTakeTimeOut.expires = jiffies + timeout;
+		add_timer(&mot82XXhscTakeTimeOut);
+		return 0;
+	}
+
+	mot82XXhscTakeTimeOutFunc(bus);
+	return 0;
+}
+
+/*
+ * Release the bus.
+ */
+static int
+mot82XXhscReleaseBus(int bus)
+{
+	mot82XXhscClrBits(&MotHscInfo.Regs->BusControl[bus],
+					MOTHSC_XFR_CTL1 | MOTHSC_XFR_CTL2);
+	return 0;
+}
+
+/*
+ * The function retrieves an event message data structure fromt he free
+ * list.  If the free list is empty it will kmalloc a new chunck of memory
+ * from the OS, format it and add it to the list of free elements.  This 
+ * memory is only returned to the OS at system reboot.
+ */
+HscMessage *
+mot82XXhscAllocMessage(void)
+{
+	HscMessage *NewMessPtr;
+	HscMessage *TmpMessPtr = MotMessageFreeList;
+	int loop;
+
+	MotMessageFreeList = MotMessageFreeList->Next;
+	TmpMessPtr->Next = NULL;
+
+	if (MotMessageFreeList == NULL) {
+		MotMessageFreeList = kmalloc(MOTHSC_MESSAGE_CHUNK_SIZE *
+					sizeof(HscMessage), GFP_ATOMIC);
+
+		NewMessPtr = MotMessageFreeList;
+		for (loop = 0; loop < MOTHSC_MESSAGE_CHUNK_SIZE-1; loop++) {
+			NewMessPtr->Event = 0;
+			NewMessPtr->Unit = 0;
+			NewMessPtr->Val = 0;
+			NewMessPtr->Next = NewMessPtr + 1;
+			NewMessPtr++;
+		}
+		NewMessPtr->Event = 0;
+		NewMessPtr->Unit = 0;
+		NewMessPtr->Val = 0;
+		NewMessPtr->Next = NULL;
+	}
+
+	return TmpMessPtr;
+}
+
+/*
+ * Place an event message back on the free list.
+ */
+void
+mot82XXhscFreeMessage(HscMessage *message)
+{
+	message->Event = 0;
+	message->Unit = 0;
+	message->Val = 0;
+	message->Next = MotMessageFreeList;
+	MotMessageFreeList = message;
+}
+
+/*
+ * Allocate, format and fill in the event message data.  It is
+ * then placed on the specified PID's event queue or all event
+ * queues and the controlling process{s} are notified events
+ * are waiting.
+ */
+void
+mot82XXhscSendEvent(int pid, int event, int unit, int val)
+{
+	HscEventRequesters *Requester = MotEventRequestersList;
+
+	while(Requester) {
+		if (pid && (Requester->Pid != pid)) {
+			Requester = Requester->Next;
+			continue;
+		}
+
+		if (Requester->Head == (HscMessage *)NULL) {
+			Requester->Head = mot82XXhscAllocMessage();
+			Requester->Tail = Requester->Head;
+		} else {
+			Requester->Tail->Next = mot82XXhscAllocMessage();
+			Requester->Tail = Requester->Tail->Next;
+		}
+
+		Requester->Tail->Event = event;
+		Requester->Tail->Unit = unit;
+		Requester->Tail->Val = val;
+
+		/* Send a SIGIO to the requesting process. */
+		kill_fasync(&Requester->Fasyncptr, SIGIO, POLL_IN);
+		Requester = Requester->Next;
+	}
+}
+
+int
+mot82XXhscReportHostID(void)
+{
+	return MotHscInfo.Host;
+}
+
+int
+mot82XXhscBusStatus(int bus)
+{
+	int state;
+
+	state = (MOTHSC_READREG(BusControl[bus]) & 0x1e) >> 1;
+	
+	if (state == HSC_STATE_MINE) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+mot82XXhscEnumStatus(int bus)
+{
+	if (MOTHSC_READREG(IntMask) & (MOTHSC_ENUMA << bus)) {
+		return 1;
+	} else {
+		return 0;
+	}
+}
+
+void
+mot82XXhscSetSlotBits(int slot, int bits, int state)
+{
+	if (state) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->Slot[slot], bits);
+	} else {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Slot[slot], bits);
+	}
+	return;
+}
+
+int
+mot82XXhscCheckHealthy(int slot)
+{
+	if (MOTHSC_READREG(Slot[slot]) & MOTHSC_HEALTHY) {
+		return 1;
+	}
+
+	return 0;
+}
+
+int
+mot82XXhscCheckSlotBits(int slot, int bits)
+{
+	if (MOTHSC_READREG(Slot[slot]) & bits) {
+		return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * This is the external function to allocate a bus and set power and
+ * connect on all its slots.  In an earlier version this code was
+ * called directly from the HSC init function.
+ */
+int
+mot82XXhscAllocateAndInitBus(int bus)
+{
+	int slot, start_slot;
+	int state;
+	int retval;
+
+	/* Disable enum processing while doing this */
+	mot82XXhscSetEnumMask(MOTHSC_BUSA + bus, MOT82XXHSC_CLEAR);
+
+	if (bus)
+		start_slot = 10;
+	else
+		start_slot = 0;
+
+	state = (MOTHSC_READREG(BusControl[bus]) & 0x1e) >> 1;
+	if (state == HSC_STATE_MINE) {
+		retval = MOTHSC_BUS_WAS_PRESENT;
+	} else {
+		mot82XXhscAttachBus(bus, 0);
+		retval = MOTHSC_BUS_NOW_PRESENT;
+	}
+
+	for (slot = start_slot; slot < start_slot + 6; slot++) {
+		mot82XXhscSetBits(&MotHscInfo.Regs->Slot[slot],
+				MOTHSC_POWER_ON | MOTHSC_CONNECT);
+		udelay(10);
+	}
+
+	return retval;
+}
+
+/*
+ * Deallocat the same bus as allocated above.
+ */
+void
+mot82XXhscDeallocateAndShutdownBus(int bus)
+{
+	int slot, start_slot;
+	int state;
+
+	/* Disable enum processing while doing this */
+	mot82XXhscSetEnumMask(MOTHSC_BUSA + bus, MOT82XXHSC_CLEAR);
+
+	if (bus)
+		start_slot = 10;
+	else
+		start_slot = 0;
+
+	state = (MOTHSC_READREG(BusControl[bus]) & 0x1e) >> 1;
+	if (state != HSC_STATE_MINE) {
+		return;
+	}
+
+
+	for (slot = start_slot; slot < start_slot + 6; slot++) {
+		mot82XXhscClrBits(&MotHscInfo.Regs->Slot[slot],
+				MOTHSC_POWER_ON | MOTHSC_CONNECT);
+	}
+
+	mot82XXhscReleaseBus(bus);
+
+	return;
+}
+
+static HSI_INIT initData;
+
+/*
+ * The following functions are part of the PICMG 2.12 control functionality.
+ * They are used by functionality in the piphs.c file.
+ */
+
+/*
+ * Initialize the 2.12 functionality with this drivers informations.
+ */
+int
+mot82XXhscHsiInit(void)
+{
+	HSI_STATUS status;
+	void * pExt;
+	struct tq_struct noDpc;
+
+	/* Initialize the PICMG 2.12 Driver */
+	noDpc.sync = 0;
+	noDpc.routine = NULL;
+	noDpc.data = NULL;
+
+	initData.DevExtSize = 0;
+	initData.Intr = 0;
+	initData.IntrFlags = 0;
+	initData.pDevId = NULL;
+	initData.QueryEnumState = mot82XXhscHsiQueryEnumState;
+	initData.CheckEnumInterrupt = mot82XXhscHsiCheckEnumInterrupt;
+	initData.Enable = mot82XXhscHsiEnableEnums;
+	initData.Disable = mot82XXhscHsiDisableEnums;
+	initData.Isr = (INTERRUPT_SERVICE_ROUTINE) NULL;
+	initData.Dpc = noDpc;
+
+	if ((status = HsiPlatformInitialize(&initData, &pExt)) != 0) {
+		return mot82XXhscHsiConvertStatus(status);
+	}
+	return HSI_STATUS_SUCCESS;
+}
+
+/*
+ * Verify this is the correct driver.
+ */
+BOOLEAN
+mot82XXhscHsiCheckEnumInterrupt(void *pDeviceId)
+{
+	return (pDeviceId == hsi_platform_data.pDevId);
+}
+
+/*
+ * Return an indication of whether the ENUM signal is set or not.
+ */
+BOOLEAN
+mot82XXhscHsiQueryEnumState(void)
+{
+	unsigned int StateA, StateB;
+	unsigned int IntReg = MOTHSC_READREG(IntMask);
+
+	StateA = (MOTHSC_READREG(BusControl[0]) & 0x1e) >> 1;
+	StateB = (MOTHSC_READREG(BusControl[1]) & 0x1e) >> 1;
+
+	if (((IntReg & MOTHSC_A_STATE) && (StateA == HSC_STATE_MINE)) ||
+	    ((IntReg & MOTHSC_B_STATE) && (StateB == HSC_STATE_MINE))) {
+		return TRUE;
+	}
+
+	return FALSE;
+}
+
+/*
+ * Enable the ENUM interrupts.  Must not forget to check and see of we
+ * own the bus first.
+ */
+HSI_STATUS
+mot82XXhscHsiEnableEnums(void)
+{
+	int chk_val = MOTHSC_XFR_CTL1|MOTHSC_XFR_CTL2;
+
+	if ((MOTHSC_READREG(BusControl[MOTHSC_BUSA]) & chk_val) == chk_val) {
+		if (mot82XXhscSetEnumMask(MOTHSC_BUSA, MOT82XXHSC_SET)) {
+			return HSI_STATUS_FAILURE;
+		}
+	}
+
+	if ((MOTHSC_READREG(BusControl[MOTHSC_BUSB]) & chk_val) == chk_val) {
+		if (mot82XXhscSetEnumMask(MOTHSC_BUSB, MOT82XXHSC_SET)) {
+			return HSI_STATUS_FAILURE;
+		}
+	}
+
+	return HSI_STATUS_SUCCESS;
+}
+
+/*
+ * Disable the ENUM interrupts.  Must not forget to check and see of we
+ * own the bus first.
+ */
+HSI_STATUS
+mot82XXhscHsiDisableEnums(void)
+{
+	int chk_val = MOTHSC_XFR_CTL1|MOTHSC_XFR_CTL2;
+
+	if ((MOTHSC_READREG(BusControl[MOTHSC_BUSA]) & chk_val) == chk_val) {
+		if (mot82XXhscSetEnumMask(MOTHSC_BUSA, MOT82XXHSC_CLEAR)) {
+			return HSI_STATUS_FAILURE;
+		}
+	}
+
+	if ((MOTHSC_READREG(BusControl[MOTHSC_BUSB]) & chk_val) == chk_val) {
+		if (mot82XXhscSetEnumMask(MOTHSC_BUSB, MOT82XXHSC_CLEAR)) {
+			return HSI_STATUS_FAILURE;
+		}
+	}
+
+	return HSI_STATUS_SUCCESS;
+}
+
+/*
+ * Convert status values from piphs to values the driver can
+ * return to user level errno's.
+ */
+int
+mot82XXhscHsiConvertStatus(HSI_STATUS status)
+{
+	switch (status) {
+	case HSI_STATUS_SUCCESS :
+		return 0;
+	case HSI_STATUS_NO_MEMORY :
+		return -ENOMEM;
+	case HSI_STATUS_INVALID_PARAMETER :
+		return -EINVAL;
+	case HSI_STATUS_NOT_IMPLEMENTED :
+		return -ENOSYS;
+	case HSI_STATUS_NO_SUCH_DEVICE :
+		return -ENODEV;
+	case HSI_STATUS_NO_DATA_DETECTED :
+		return -ENODATA;
+	case HSI_STATUS_OPERATION_NOT_APPLICABLE :
+		return -EPERM;
+	case HSI_STATUS_NOT_AVAILABLE :
+		return -EBUSY;
+	default :
+		return -EPERM;     // HSI_STATUS_FAILURE goes here too
+	}
+}
+
+#ifdef CONFIG_CHASSIS_CONTROL
+int
+mot82xxChassisStatusFunc(unsigned int arg, unsigned int mode)
+{
+	return mot82XXhscSetLed(arg, mode);
+}
+
+int
+mot82xxChassisAlarmFunc(unsigned int arg, unsigned int mode)
+{
+	return mot82XXhscSetAlarm(arg, mode);
+}
+#endif
+
diff -u -r --new-file linux/drivers/ha/cpci/mot82XXhsc.h ha/drivers/ha/cpci/mot82XXhsc.h
--- linux/drivers/ha/cpci/mot82XXhsc.h	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/mot82XXhsc.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,272 @@
+/*
+ * mot82XXhsc.h
+ *
+ * Motorola 82XX hot swap controller driver.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef MOT82XXHSC_DRIVER_H
+#define MOT82XXHSC_DRIVER_H
+
+#include <linux/mot82XXhsc.h>
+
+/* Couple of prototypes usefull to other files. */
+int	mot82XXhscReportHostID(void);
+int	mot82XXhscBusStatus(int);
+int	mot82XXhscEnumStatus(int);
+void	mot82XXhscSetSlotBits(int, int, int);
+int	mot82XXhscCheckSlotBits(int, int);
+int	mot82XXhscSetEnumMask(int, int);
+
+/* Number of bits to check in the interrupt register. */
+#define MOTHSC_REG_SIZE 32
+
+#define MOTHSC_BUSA	0
+#define MOTHSC_BUSB	1
+
+/* Standard bits in control registers */
+#define MOTHSC_PRESENT	    0x1
+#define MOTHSC_POWER_ON	    0x2
+#define MOTHSC_IGN_HEALTHY  0x4
+#define MOTHSC_RESET	    0x8
+#define MOTHSC_CONNECT	    0x10
+#define MOTHSC_CONNECTED    0x20
+#define MOTHSC_HEALTHY	    0x40
+#define MOTHSC_LED1	    0x100
+#define MOTHSC_LED2	    0x200
+#define MOTHSC_LED3	    0x400
+#define MOTHSC_H110_RESET   0x1000
+#define MOTHSC_ACTIVE	    0x1000000
+#define MOTHSC_INT_STATUS   0x4000000
+#define MOTHSC_INTA_ENABLE  0x8000000
+#define MOTHSC_INTB_ENABLE  0x10000000
+#define MOTHSC_INTC_ENABLE  0x18000000
+#define MOTHSC_CMD_CLEAR    0x20000000
+#define MOTHSC_CMD_SET	    0x40000000
+#define MOTHSC_CMD_WRITE    0x60000000
+
+/* Masks defining bits that cause interrupts in the specified registers. */
+#define MOTHSC_SLOTINT	    (MOTHSC_PRESENT|MOTHSC_CONNECTED|MOTHSC_HEALTHY)
+#define MOTHSC_HOSTINT	    (MOTHSC_CONNECTED|MOTHSC_HEALTHY)
+#define MOTHSC_HSCINT	    (MOTHSC_INSERTION|MOTHSC_REMOVAL|MOTHSC_CONNECTED)
+
+/* Special bits for HSC/Bridge slots */
+#define MOTHSC_INSERTION    0x2
+#define MOTHSC_REMOVAL      0x4
+#define MOTHSC_INSTALLED    0x8
+#define MOTHSC_EJECTOR      0x10
+#define MOTHSC_HSC_H110_RES 0x40
+
+/* Special bits for Power Supply */
+#define MOTHSC_PS_ON        0x2
+#define MOTHSC_PS_GOOD      0x4
+#define MOTHSC_COOL_ALARM   0x8
+#define MOTHSC_COOL_FAULT   0x10
+#define MOTHSC_PS_LED1      0x100
+#define MOTHSC_PS_LED2      0x200
+#define MOTHSC_FAN_LED1     0x400
+#define MOTHSC_FAN_LED2     0x800
+#define MOTHSC_FAN_PRESENT  0x1000
+#define MOTHSC_FAN_LOW      0x2000
+#define MOTHSC_FAN_FAULT    0x4000
+
+/* Special bits for peripheral bays */
+#define MOTHSC_PBAY_OWNDEV  0x4
+#define MOTHSC_PBAY_LED1    0x100
+#define MOTHSC_PBAY_LED2    0x200
+
+/* Special bits for LED register */
+#define MOTHSC_LED4         0x800
+
+/* Speical bits for alarm register */
+#define MOTHSC_ALRM_CRIT    0x100
+#define MOTHSC_ALRM_MAJOR   0x200
+#define MOTHSC_ALRM_MINOR   0x400
+#define MOTHSC_ALRM_RACK    0x800
+
+/* Bus control register bits */
+#define MOTHSC_XFR_CTL1     0x2
+#define MOTHSC_XFR_CTL2     0x4
+#define MOTHSC_XFR_STS1     0x8
+#define MOTHSC_XFR_STS2     0x10
+#define MOTHSC_SOFT_TRANS   0x20
+#define MOTHSC_LOCK         0x40
+#define MOTHSC_HOST_DOMAIN  0x80
+#define MOTHSC_STATE_12     0xc000
+#define MOTHSC_STATE_MASK   0xf000
+#define MOTHSC_ALLOW	    0x10000
+
+/* Bus states */
+#define HSC_STATE_FREE	    0x0
+#define HSC_STATE_OTHER     0xc
+#define HSC_STATE_REQUESTED 0xe
+#define HSC_STATE_TRAN_STRT 0x7
+#define HSC_STATE_STOPED    0x9
+#define HSC_STATE_TRAN_ACK  0x6
+#define HSC_STATE_ENABLE    0xb
+#define HSC_STATE_TRAN_DONE 0xf
+#define HSC_STATE_MINE	    0x3
+
+/* Bits bir eeprom register */
+#define MOTHSC_FPGA_DOUT    0x2
+#define MOTHSC_FPGA_CLK     0x4
+#define MOTHSC_FPGA_PROG    0x8
+#define MOTHSC_FPGA_RESET   0x10
+#define MOTHSC_FPGA_CE      0x20
+#define MOTHSC_FPGA_SER_EN  0x40
+#define MOTHSC_FPGA_DIN     0x80
+
+/* Interrupt mask register bits */
+#define MOTHSC_INTA         0x2
+#define MOTHSC_INTB         0x4
+#define MOTHSC_INTC         0x8
+#define MOTHSC_ENUMA        0x10
+#define MOTHSC_ENUMB        0x20
+#define MOTHSC_H110_GLOB    0x40
+#define MOTHSC_A_STATE      0x2000
+#define MOTHSC_B_STATE      0x4000
+#define MOTHSC_PROP_ENUM    0x8000
+
+/* Bits in the interrupt status registers */
+#define MOTHSC_INT_SLOT1    0x1
+#define MOTHSC_INT_SLOT2    0x2
+#define MOTHSC_INT_SLOT3    0x4
+#define MOTHSC_INT_SLOT4    0x8
+#define MOTHSC_INT_SLOT5    0x10
+#define MOTHSC_INT_SLOT6    0x20
+#define MOTHSC_INT_HOST1    0x40
+#define MOTHSC_INT_HSC2     0x80
+#define MOTHSC_INT_HOST2    0x100
+#define MOTHSC_INT_HSC1     0x200
+#define MOTHSC_INT_SLOT11   0x400
+#define MOTHSC_INT_SLOT12   0x800
+#define MOTHSC_INT_SLOT13   0x1000
+#define MOTHSC_INT_SLOT14   0x2000
+#define MOTHSC_INT_SLOT15   0x4000
+#define MOTHSC_INT_SLOT16   0x8000
+#define MOTHSC_INT_PBAY1    0x10000
+#define MOTHSC_INT_PBAY2    0x20000
+#define MOTHSC_INT_PBAY3    0x40000
+#define MOTHSC_INT_PBAY4    0x80000
+#define MOTHSC_INT_MASK     0x800000
+#define MOTHSC_INT_PS1	    0x4000000
+#define MOTHSC_INT_PS2	    0x8000000
+#define MOTHSC_INT_PS3	    0x10000000
+#define MOTHSC_INT_ALARM    0x20000000
+#define MOTHSC_INT_BUSA	    0x40000000
+#define MOTHSC_INT_BUSB	    0x80000000
+
+/* Return values for exported allocate bus routine */
+#define MOTHSC_BUS_WAS_PRESENT 0
+#define MOTHSC_BUS_NOW_PRESENT 1
+
+
+/* Various stats for the hsc driver.  This could use more work. */
+
+typedef struct mot9216hsc_stats {
+	int	TotalOpens;
+	int	CurOpens;
+	int	BogusCmds;
+} HscStats;
+
+/* Register access control data structure. */
+typedef struct mot82XXhsc_regs {
+	volatile unsigned int	Slot[MOTHSC_NUM_SLOTS];  	/* 0x0 - 0x3c cPCI slots */
+	volatile unsigned int	unused1[16];	/* 0x40 - 0x7c Not implement */
+	volatile unsigned int	Ps[MOTHSC_NUM_PS];	/* 0x80 - 0x8c Power Supply */
+	volatile unsigned int	unused2;
+	volatile unsigned int	PBay[MOTHSC_NUM_PBAY];	/* 0x90 - 0x9c Peripheral bay */
+	volatile unsigned int	unsused3[12];	/* 0xa0 - 0acc Not implement */
+	volatile unsigned int	IntStatMask;
+	volatile unsigned int	IntStatus[MOTHSC_NUM_INTSTAT];
+	volatile unsigned int	unused3[2];
+	volatile unsigned int	BusControl[MOTHSC_NUM_BUS];
+	volatile unsigned int	EEprom;
+	volatile unsigned int	SysLed;
+	volatile unsigned int	Alarm;
+	volatile unsigned int	IntMask;
+} HscRegs;
+
+/* Driver instance information. */
+typedef struct mot82XXhsc_info {
+	struct pci_dev	*Device;
+	int		Major;
+	int		Irq;
+	int		Host;
+	HscRegs		*Regs;
+	unsigned int	PBayOldBits[MOTHSC_NUM_PBAY];
+	unsigned int	PowerOldBits[MOTHSC_NUM_PS];
+	unsigned int	SlotOldBits[MOTHSC_NUM_SLOTS];
+	unsigned int	SlotOldIntBits[MOTHSC_NUM_SLOTS];
+	unsigned int	HostOldBits[MOTHSC_NUM_SLOTS];
+	unsigned int	HostOldIntBits[MOTHSC_NUM_SLOTS];
+	unsigned int	HscOldBits[MOTHSC_NUM_SLOTS];
+	unsigned int	HscOldIntBits[MOTHSC_NUM_SLOTS];
+	int		EnumOldState[2];
+	int		EnumEnabled[2];
+	int		BusTakeoverAllowed[2];
+	int		LastBusControl[2];
+} HscInfo;
+
+/* Event message data structures. */
+#define MOTHSC_MESSAGE_CHUNK_SIZE	128
+
+typedef struct mot82XXhsc_message {
+        struct mot82XXhsc_message *Next;
+        int             Event;
+        int             Unit;
+        int             Val;
+} HscMessage;
+
+/* Event requestors control. */
+#define MOTHSC_MAX_EVENT_REQUESTERS	32
+
+typedef struct mot82XXhsc_event_users {
+	struct mot82XXhsc_event_users *Next;
+	pid_t			Pid;
+	HscMessage		*Head;
+	HscMessage		*Tail;
+	struct fasync_struct	*Fasyncptr;
+} HscEventRequesters;
+
+/* Interrupt bit <=> sub control function mapping data. */
+typedef struct mot82XXhsc_reginfo {
+	volatile unsigned int	*Reg;
+	int			SubInfo;
+	void			(*IntHandler)(volatile unsigned int *, int);
+} HscRegInfo;
+
+/* Some macros used in the drivers.  */
+#define MOTHSC_READREG(Reg) le32_to_cpu(MotHscInfo.Regs->Reg)
+
+#define MOTHSC_GET_REG_FROM_BIT(bit)        &MotHscRegInfo[(bit)];
+
+#define MOT_HSC_CALL_INT_HANDLER(bit, arg2) \
+	      (MotHscRegInfo[(bit)].IntHandler)((arg2)->Reg, (arg2)->SubInfo)
+
+#endif /* MOT82XXHSC_DRIVER_H */
diff -u -r --new-file linux/drivers/ha/cpci/mot_cpci.c ha/drivers/ha/cpci/mot_cpci.c
--- linux/drivers/ha/cpci/mot_cpci.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/mot_cpci.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,753 @@
+/*
+ * mot_cpci.c
+ *
+ * Motorola MCP750 and CPV5350 specific cPCI control routines.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_auto.h>
+#include <linux/cpci.h>
+#include <asm/pci.h>
+#include <asm/delay.h>
+#include "mot82XXhsc.h"
+#include "mot_enum.h"
+#include "cpci_core.h"
+
+int  motCpci_early_config_bus(struct pci_controller *, int, int);
+void motCpci_find_driver(int);
+
+int  mot82XXhsc_init(void);
+int  motEnum_init(void);
+
+int  CpciDelBus(int, int);
+
+#ifdef CONFIG_X86
+struct pci_ops *pci_check_direct(void);
+struct pci_ops *pci_find_bios(void);
+
+extern struct pci_ops *pci_root_ops;
+#endif
+
+#ifdef CONFIG_PPC
+#define MOTHSC_BUS1_DEVFN PCI_DEVFN(0x14, 0)
+#define MOTHSC_BUS2_DEVFN PCI_DEVFN(0x18, 0)
+#define HSC_DEVFN PCI_DEVFN(0x16, 0)
+#else
+#define MOTHSC_BUS1_DEVFN PCI_DEVFN(0x11, 0)
+#define MOTHSC_BUS2_DEVFN PCI_DEVFN(0x0d, 0)
+#define HSC_DEVFN PCI_DEVFN(0xb, 0)
+#define AGP_DEVFN PCI_DEVFN(0x1, 0)
+#define PIXX4_HB_DEVFN PCI_DEVFN(0x7, 0)
+#endif
+
+#define NUM_HA_SLOTS 16
+
+unsigned int CpciHaIoSize[] = {
+	CONFIG_MOT_82XX_SLOT1_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT2_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT3_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT4_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT5_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT6_IO_SIZE,
+	0, 0, 0, 0,
+	CONFIG_MOT_82XX_SLOT11_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT12_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT13_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT14_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT15_IO_SIZE,
+	CONFIG_MOT_82XX_SLOT16_IO_SIZE,
+};
+
+unsigned int CpciHaMemSize[] = {
+	CONFIG_MOT_82XX_SLOT1_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT2_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT3_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT4_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT5_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT6_MEM_SIZE,
+	0, 0, 0, 0,
+	CONFIG_MOT_82XX_SLOT11_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT12_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT13_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT14_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT15_MEM_SIZE,
+	CONFIG_MOT_82XX_SLOT16_MEM_SIZE,
+};
+
+CpciNodeInfo MotHaBusInfo[] = {
+	{NULL, 0x0, 0x0, 0, 0, 0x07, 0x37, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0, 0x0, 0, 0, 0x47, 0x77, 0x0, 0x0, 0x0, 0x0}
+};
+
+CpciNodeInfo MotHaSlotInfo[] = {
+	{NULL, 0X7,  PCI_DEVFN(0xe,0), 0, 0, 0x08, 0x0f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xd,0), 0, 0, 0x10, 0x17, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xc,0), 0, 0, 0x18, 0x1f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xb,0), 0, 0, 0x20, 0x27, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xa,0), 0, 0, 0x28, 0x2f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0x9,0), 0, 0, 0x30, 0x37, 0x0, 0x0, 0x0, 0x0},
+
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+
+	{NULL, 0x47, PCI_DEVFN(0xe,0), 0, 0, 0x48, 0x4f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xd,0), 0, 0, 0x50, 0x57, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xc,0), 0, 0, 0x58, 0x5f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xb,0), 0, 0, 0x60, 0x67, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xa,0), 0, 0, 0x68, 0x6f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0x9,0), 0, 0, 0x70, 0x77, 0x0, 0x0, 0x0, 0x0}
+};
+
+CpciInfo MotHaCpciInfo = {0,	    /* Chassis type to filled in below */
+			  2,	    /* Number of buses. */
+			  {0, 10},  /* Bus start slot numbers. */
+			  {5, 15}   /* Bus end slot numbers. */
+			 };
+
+#define NUM_HS_SLOTS 7
+
+unsigned int CpciHsIoSize[] = {
+	CONFIG_MOT_GEN_SLOT1_IO_SIZE,
+	CONFIG_MOT_GEN_SLOT2_IO_SIZE,
+	CONFIG_MOT_GEN_SLOT3_IO_SIZE,
+	CONFIG_MOT_GEN_SLOT4_IO_SIZE,
+	CONFIG_MOT_GEN_SLOT5_IO_SIZE,
+	CONFIG_MOT_GEN_SLOT6_IO_SIZE,
+	CONFIG_MOT_GEN_SLOT7_IO_SIZE,
+};
+
+unsigned int CpciHsMemSize[] = {
+	CONFIG_MOT_GEN_SLOT1_MEM_SIZE,
+	CONFIG_MOT_GEN_SLOT2_MEM_SIZE,
+	CONFIG_MOT_GEN_SLOT3_MEM_SIZE,
+	CONFIG_MOT_GEN_SLOT4_MEM_SIZE,
+	CONFIG_MOT_GEN_SLOT5_MEM_SIZE,
+	CONFIG_MOT_GEN_SLOT6_MEM_SIZE,
+	CONFIG_MOT_GEN_SLOT7_MEM_SIZE,
+};
+
+CpciNodeInfo MotHsBusInfo[] = {
+	{NULL, 0x0, 0x0, 0, 0, 0x07, 0x3f, 0x0, 0x0, 0x0, 0x0}
+};
+
+CpciNodeInfo MotHsSlotInfo[] = {
+	{NULL, 0x7,  PCI_DEVFN(0xf,0), 0, 0, 0x08, 0x0f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xe,0), 0, 0, 0x10, 0x17, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xd,0), 0, 0, 0x18, 0x1f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xc,0), 0, 0, 0x20, 0x27, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xb,0), 0, 0, 0x28, 0x2f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xa,0), 0, 0, 0x30, 0x37, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0x9,0), 0, 0, 0x38, 0x3f, 0x0, 0x0, 0x0, 0x0}
+};
+
+CpciInfo MotHsCpciInfo = {CPCI_CHASSIS_GEN_HOTSWAP, /* Chassis type */
+			  1,	   /* Number of buses. */
+			  {0, 0},  /* Bus start slot numbers. */
+			  {6, 0}   /* Bus end slot numbers. */
+			 };
+
+static struct pci_controller* MainHose;
+
+#ifdef CONFIG_PPC
+unsigned char MotCpciIrqs[2][4] = {
+	{24, 25, 26, 27},
+	{28, 29, 30, 31}
+};
+#endif
+#ifdef CONFIG_X86
+unsigned char MotCpciIrqs[2][4];
+#endif
+
+int MotCpciNumSlots;
+
+#ifdef CONFIG_PPC
+#define PCI_LOWER_IO  0x00000000
+#define PCI_UPPER_IO  0x0fffffff
+#define PCI_LOWER_MEM 0x00000000
+#define PCI_UPPER_MEM 0x3cfbffff
+#define ISA_IO_BASE   PREP_ISA_IO_BASE
+#define ISA_MEM_BASE  PREP_ISA_MEM_BASE
+
+#define PCI_IO_CPCI_START 0x3ff8000
+#define PCI_MEM_CPCI_START 0x38000000
+#endif
+#ifdef CONFIG_X86
+#define PCI_LOWER_IO  0x3000
+#define PCI_UPPER_IO  0x10000
+#define PCI_LOWER_MEM 0x50000000
+#define PCI_UPPER_MEM 0xf4000000
+#define ISA_IO_BASE   0x0
+#define ISA_MEM_BASE  0x0
+
+#define PCI_IO_CPCI_START 0x010000
+#define PCI_MEM_CPCI_START 0xe8000000
+
+int
+motCpci_ignore_agp(struct pci_controller *hose, int bus, int devfn)
+{
+	return 0;
+}
+#endif
+
+struct pci_auto_addrs PciAddrs = {
+	PCI_LOWER_IO, PCI_UPPER_IO, PCI_LOWER_MEM, PCI_UPPER_MEM
+};
+
+/*
+ * Provide the find bridges functionality needed from the architecture
+ * specific boot code.  Instead of the old method of using the firmware
+ * set value, do pci autoscan and with exceptions for the cPCI bridge chips.
+ */
+void __init
+motCpci_find_bridges(void)
+{
+	unsigned int Bar0;
+	unsigned short Vendor;
+	unsigned short Device;
+	unsigned int * HscRegs;
+	unsigned short Command;
+	int MotCpciHostID = -1;
+	int loop;
+	int LastIo;
+	int LastMem;
+#ifdef CONFIG_X86
+	unsigned char Pirq;
+#endif
+
+#ifdef CONFIG_X86
+	printk("Initialize the PCI bridge tree for the Motorola CPV5350 cPCI Host Processor Board\n");
+#else
+	printk("Initialize the PCI bridge tree for the Motorola MPC750 cPCI Host Processor Board\n");
+#endif
+
+#ifdef CONFIG_PPC
+	MainHose = pcibios_alloc_controller();
+#endif
+#ifdef CONFIG_X86
+	MainHose = pciauto_alloc_controller();
+#endif
+	if (!MainHose)
+		return;
+
+	MainHose->first_busno = 0;
+	MainHose->last_busno = 0xff;
+	MainHose->pci_mem_offset = ISA_MEM_BASE;
+	MainHose->mem_space.start = PciAddrs.mem_start;
+	MainHose->mem_space.end = PciAddrs.mem_end;
+	MainHose->io_base_virt = (void *)ISA_IO_BASE;
+	MainHose->io_space.start = PciAddrs.io_start;
+	MainHose->io_space.end = PciAddrs.io_end;
+	MainHose->mem_resources[0].end = 0xffffffff;
+
+#ifdef CONFIG_X86
+	MainHose->ops = pci_root_ops;
+	MainHose->cfg_addr = (unsigned int *)NULL;  /* Not used on intel arch */
+	MainHose->cfg_data = (unsigned char *)NULL;
+
+	/* Need to get the PIRQ values and set eny not initilaized */
+	for (loop = 0; loop < 4; loop++) {
+		early_read_config_byte(MainHose, 0, PIXX4_HB_DEVFN,
+				       0x60 + loop, &Pirq);
+
+		if (Pirq == 0x80) {
+			Pirq = 5;
+			early_write_config_byte(MainHose, 0, PIXX4_HB_DEVFN,
+						0x60 + loop, Pirq);
+		}
+
+		MotCpciIrqs[0][loop] = Pirq;
+		MotCpciIrqs[1][loop] = Pirq;
+	}
+#endif
+
+#ifdef CONFIG_PPC
+	pplus_init_resource(&MainHose->io_resource, 0x00000000, 0x0fffffff, IORESOURCE_IO);
+	pplus_init_resource(&MainHose->mem_resources[0], 0xc0000000, 0xfdffffff, IORESOURCE_MEM);
+
+	setup_indirect_pci(MainHose, 0x80000cf8, 0x80000cfc);
+	pplus_set_VIA_IDE_legacy();
+#endif
+
+	early_read_config_word(MainHose, 0, HSC_DEVFN, PCI_VENDOR_ID, &Vendor);
+	early_read_config_word(MainHose, 0, HSC_DEVFN, PCI_DEVICE_ID, &Device);
+
+	/* Set the chassis type and number of slots variables. */
+	if (Vendor == PCI_VENDOR_ID_MOTOROLA) {
+		switch (Device) {
+	    	case PCI_DEVICE_ID_MOTOROLA_CPX8216:
+			MotCpciNumSlots = NUM_HA_SLOTS;
+			MotHaCpciInfo.ChassisType = CPCI_CHASSIS_MOT_CPX8216;
+			break;
+	     	case PCI_DEVICE_ID_MOTOROLA_CPX8216A:
+			MotCpciNumSlots = NUM_HA_SLOTS;
+			MotHaCpciInfo.ChassisType = CPCI_CHASSIS_MOT_CPX8216A;
+			break;
+	     	case PCI_DEVICE_ID_MOTOROLA_CPX8216T:
+			MotCpciNumSlots = NUM_HA_SLOTS;
+			MotHaCpciInfo.ChassisType = CPCI_CHASSIS_MOT_CPX8216T;
+			break;
+	     	case PCI_DEVICE_ID_MOTOROLA_CPX8221:
+			MotCpciNumSlots = NUM_HA_SLOTS;
+			MotHaCpciInfo.ChassisType = CPCI_CHASSIS_MOT_CPX8221;
+			break;
+		default:
+			MotCpciNumSlots = NUM_HS_SLOTS;
+		}
+	} else {
+		MotCpciNumSlots = NUM_HS_SLOTS;
+	}
+
+	if (MotCpciNumSlots == NUM_HA_SLOTS) {
+		/* Before changing the PCI values, map in the hotswap controller
+	 	 * and find out which host (A or B) linux is running on.  This 
+	 	 * information is needed to decide bus numbering on the cPCI
+		 * busses.
+	 	 */
+		early_read_config_dword(MainHose, 0, HSC_DEVFN, PCI_BASE_ADDRESS_0, &Bar0);
+#ifdef CONFIG_PPC
+		Bar0 += 0xc0000000;
+#endif
+
+		HscRegs = (unsigned int *)ioremap(Bar0, 0xff);
+
+		if (le32_to_cpu(HscRegs[58]) & MOTHSC_HOST_DOMAIN) {
+			MotCpciHostID = 1;
+		} else {
+			MotCpciHostID = 0;
+		}
+
+		iounmap((void *)HscRegs);
+
+		if (!MotCpciHostID) {
+			MotHaBusInfo[0].DevFn = MOTHSC_BUS1_DEVFN;  /* Bus A */
+			MotHaBusInfo[1].DevFn = MOTHSC_BUS2_DEVFN;  /* Bus B */
+		} else {
+			MotHaBusInfo[0].DevFn = MOTHSC_BUS2_DEVFN;  /* Bus A */
+			MotHaBusInfo[1].DevFn = MOTHSC_BUS1_DEVFN;  /* Bus B */
+		}
+
+		/* Tell the cPCI core routines where the slot table exists. */
+		CpciBuses = MotHaBusInfo;
+		CpciSlots = MotHaSlotInfo;
+		CpciInfos = &MotHaCpciInfo;
+
+		/* Set some values for the two top level bridges.  These
+		 * are config cycles so ignore failures.
+		 */
+		early_read_config_word(MainHose, 0, MotHaBusInfo[0].DevFn,
+					PCI_COMMAND, &Command);
+		Command &= ~(PCI_COMMAND_IO |
+			     PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+		early_write_config_word(MainHose, 0, MotHaBusInfo[0].DevFn,
+					PCI_COMMAND, Command);
+
+		early_write_config_byte(MainHose, 0, MotHaBusInfo[0].DevFn,
+			PCI_SECONDARY_BUS, MotHaBusInfo[0].FirstBusNo);
+
+		early_write_config_byte(MainHose, 0, MotHaBusInfo[0].DevFn,
+			PCI_SUBORDINATE_BUS, MotHaBusInfo[0].LastBusNo);
+
+		early_read_config_word(MainHose, 0, MotHaBusInfo[1].DevFn,
+					PCI_COMMAND, &Command);
+		Command &= ~(PCI_COMMAND_IO |
+			     PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+		early_write_config_word(MainHose, 0, MotHaBusInfo[1].DevFn,
+					PCI_COMMAND, Command);
+
+		early_write_config_byte(MainHose, 0, MotHaBusInfo[1].DevFn,
+			PCI_SECONDARY_BUS, MotHaBusInfo[1].FirstBusNo);
+
+		early_write_config_byte(MainHose, 0, MotHaBusInfo[1].DevFn,
+			PCI_SUBORDINATE_BUS, MotHaBusInfo[1].LastBusNo);
+	} else {
+		MotHsBusInfo[0].DevFn = MOTHSC_BUS1_DEVFN;
+
+		/* Tell the cPCI core routines where the slot table exists. */
+		CpciBuses = MotHsBusInfo;
+		CpciSlots = MotHsSlotInfo;
+		CpciInfos = &MotHsCpciInfo;
+	}
+
+	/* Do not scan the cPCI bus bridget.  Let the hot insert do that later */
+	pci_excpt_setup_bridge_bdev(MainHose, 0, MOTHSC_BUS1_DEVFN,
+						motCpci_early_config_bus);
+	pci_excpt_setup_bridge_bdev(MainHose, 0, MOTHSC_BUS2_DEVFN,
+						motCpci_early_config_bus);
+#ifdef CONFIG_X86
+	pci_excpt_setup_bridge_bdev(MainHose, 0, AGP_DEVFN,
+						motCpci_ignore_agp);
+#endif
+
+	LastIo = PCI_IO_CPCI_START;
+	LastMem = PCI_MEM_CPCI_START;
+	if (MotCpciNumSlots == NUM_HA_SLOTS) {
+		for (loop = MotCpciNumSlots - 1; loop > -1; loop--) {
+
+			MotHaSlotInfo[loop].IoEnd = LastIo;
+			LastIo -= CpciHaIoSize[loop] * 1024;
+
+			if (LastIo < PciAddrs.io_start) {
+				panic("PCI system has too much IO space allocated\n");
+			}
+
+			MotHaSlotInfo[loop].IoStart = LastIo;
+
+			MotHaSlotInfo[loop].MemEnd = LastMem;
+			LastMem -= CpciHaMemSize[loop] * 1024 * 1024;
+
+			if (LastMem < PciAddrs.mem_start) {
+				panic("PCI system has too much Memory space allocated\n");
+			}
+
+			MotHaSlotInfo[loop].MemStart = LastMem;
+		}
+
+		/* Set the bus start and end address based on the correct slot addresses */
+		MotHaBusInfo[0].IoStart = MotHaSlotInfo[0].IoStart;
+		MotHaBusInfo[0].IoEnd = MotHaSlotInfo[5].IoEnd;
+		MotHaBusInfo[0].MemStart = MotHaSlotInfo[0].MemStart;
+		MotHaBusInfo[0].MemEnd = MotHaSlotInfo[5].MemEnd;
+
+		MotHaBusInfo[1].IoStart = MotHaSlotInfo[10].IoStart;
+		MotHaBusInfo[1].IoEnd = MotHaSlotInfo[15].IoEnd;
+		MotHaBusInfo[1].MemStart = MotHaSlotInfo[10].MemStart;
+		MotHaBusInfo[1].MemEnd = MotHaSlotInfo[15].MemEnd;
+	} else {
+		for (loop = MotCpciNumSlots - 1; loop > -1; loop--) {
+
+			MotHsSlotInfo[loop].IoEnd = LastIo;
+			LastIo -= CpciHsIoSize[loop] * 1024;
+
+			if (LastIo < PciAddrs.io_start) {
+				panic("PCI system has too much IO space allocated\n");
+			}
+
+			MotHsSlotInfo[loop].IoStart = LastIo;
+
+			MotHsSlotInfo[loop].MemEnd = LastMem;
+			LastMem -= CpciHsMemSize[loop] * 1024 * 1024;
+
+			if (LastMem < PciAddrs.mem_start) {
+				panic("PCI system has too much Memory space allocated\n");
+			}
+
+			MotHsSlotInfo[loop].MemStart = LastMem;
+		}
+
+		/* Set the bus start and end address based on the correct slot addresses */
+		MotHsBusInfo[0].IoStart = MotHsSlotInfo[0].IoStart;
+		MotHsBusInfo[0].IoEnd = MotHsSlotInfo[6].IoEnd;
+		MotHsBusInfo[0].MemStart = MotHsSlotInfo[0].MemStart;
+		MotHsBusInfo[0].MemEnd = MotHsSlotInfo[6].MemEnd;
+	}
+
+	if ((pciauto_bus_scan(MainHose, MainHose->first_busno, &PciAddrs)) == -1) {
+		panic("PCI system needs more than the available PCI address space\n");
+	}
+
+	if (MotCpciNumSlots == NUM_HA_SLOTS) {
+		MainHose->last_busno = MotHaBusInfo[1].LastBusNo;
+
+		/* Set the host bridge to properly cover the whole pci address space. */
+		PciAddrs.io_end = MotHaBusInfo[0].IoStart;
+		PciAddrs.mem_end = MotHaBusInfo[0].MemStart;
+		pciauto_postscan_setup_bridge(MainHose, 0, 0, MotHaBusInfo[1].LastBusNo, &PciAddrs);
+
+		/* Recode the Hose info for each slot for later use. */
+		MotHaBusInfo[0].Hose = MainHose;
+		MotHaBusInfo[1].Hose = MainHose;
+	} else {
+		MainHose->last_busno = MotHsBusInfo[0].LastBusNo;
+
+		/* Set the host bridge to properly cover the whole pci address space. */
+		PciAddrs.io_end = MotHsBusInfo[0].IoStart;
+		PciAddrs.mem_end = MotHsBusInfo[0].MemStart;
+		pciauto_postscan_setup_bridge(MainHose, 0, 0, MotHsBusInfo[0].LastBusNo, &PciAddrs);
+
+		/* Recode the Hose info for each slot for later use. */
+		MotHsBusInfo[0].Hose = MainHose;
+	}
+
+	for (loop = 0; loop < MotCpciNumSlots; loop++) {
+		CpciSlots[loop].Hose = MainHose;
+	}
+}
+
+/*
+ * This function is called from the pci autoscan routine when the cPCI
+ * bridges are found.
+ */
+int
+motCpci_early_config_bus(struct pci_controller *hose, int bus, int devfn)
+{
+	int MotBus;
+	int Slot;
+	int RetVal;
+	unsigned char SubBus;
+	unsigned short Command;
+
+	if (devfn == CpciBuses[0].DevFn) {
+		MotBus = 0;
+	} else {
+		MotBus = 1;
+	}
+
+	CpciConfigCpciBridge(hose, bus, devfn, MotBus);
+	CpciBuses[MotBus].Allocated = CPCI_SLOT_ALLOCATED;
+
+	for (Slot = CpciInfos->StartSlotNum[MotBus];
+			Slot <= CpciInfos->EndSlotNum[MotBus]; Slot++) {
+		if ((RetVal = CpciConfigSlot(Slot, MainHose, CpciBuses[MotBus].FirstBusNo)) < 0) {
+			if (RetVal == -ENOENT) {
+				/* Nothing in the slot. */
+				continue;
+			}
+
+			/* config problems on this slot so disable access */
+			early_read_config_word(hose,
+					       CpciBuses[MotBus].FirstBusNo,
+					       CpciSlots[Slot].DevFn,
+					       PCI_COMMAND, &Command);
+			Command &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+			early_write_config_word(hose,
+						CpciBuses[MotBus].FirstBusNo,
+					        CpciSlots[Slot].DevFn,
+					        PCI_COMMAND, Command);
+
+			early_read_config_byte(hose,
+					       CpciBuses[MotBus].FirstBusNo,
+					       CpciSlots[Slot].DevFn,
+					       PCI_SECONDARY_BUS, &SubBus);
+
+			early_write_config_byte(hose,
+						CpciBuses[MotBus].FirstBusNo,
+					        CpciSlots[Slot].DevFn,
+					        PCI_SUBORDINATE_BUS, SubBus);
+
+			CpciSlots[Slot].Allocated = CPCI_SLOT_INSFAILED;
+		}
+	}
+
+	return 0;
+}
+
+void
+motRouteNon0Irq(struct pci_dev *dev)
+{
+	struct pci_bus *TempBus = dev->bus;
+	unsigned int DevNum = PCI_SLOT(dev->devfn);
+
+	while (TempBus->parent->primary != TempBus->parent->secondary) {
+		DevNum += PCI_SLOT((TempBus->self)->devfn);
+		TempBus = TempBus->parent;
+	}
+
+	DevNum &= 0x03;
+
+	if (dev->bus->number > CpciBuses[0].LastBusNo) {
+		if (CpciBuses[0].DevFn == MOTHSC_BUS1_DEVFN) {
+			dev->irq = MotCpciIrqs[1][DevNum];
+		} else {
+			dev->irq = MotCpciIrqs[0][DevNum];
+		}
+	} else {
+		if (CpciBuses[0].DevFn == MOTHSC_BUS1_DEVFN) {
+			dev->irq = MotCpciIrqs[0][DevNum];
+		} else {
+			dev->irq = MotCpciIrqs[1][DevNum];
+		}
+	}
+
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (unsigned char)dev->irq);
+}
+
+/* Prototypes Mot specific functions needed externally */
+int	mot82XXhscAllocateAndInitBus(int);
+void	mot82XXhscDeallocateAndShutdownBus(int);
+int	mot82XXhscSetEnumMask(int, int);
+int	mot82XXhscCheckHealthy(int);
+
+/* This data structure contains the hardware dependent functions to
+ * provide functionality for independent code segments.
+ * */
+CpciFunc MotHaCpciFuncs = {
+	mot82XXhscAllocateAndInitBus,
+	mot82XXhscDeallocateAndShutdownBus,
+	mot82XXhscSetEnumMask,
+	mot82XXhscCheckHealthy,
+	motRouteNon0Irq
+};
+
+CpciFunc MotHsCpciFuncs = {
+	NULL,
+	NULL,
+	motEnumEnable,
+	NULL,
+	motRouteNon0Irq
+};
+
+wait_queue_head_t motCpciDomainWaitQ;
+int motCpciDomainTakeBusNums;
+extern spinlock_t CpciPciAccessLock;
+
+void
+motCpciSetDomainTakeover(int bus)
+{
+	motCpciDomainTakeBusNums |= 0x1 << bus;
+	wake_up_interruptible(&motCpciDomainWaitQ);
+
+	return;
+}
+
+int
+motCpciCatchDomainTakeover(void *arg)
+{
+	unsigned long flags;
+	int Bus;
+
+	exit_mm(current);       // release some unneeded resources
+	exit_files(current);
+	exit_fs(current);
+	                                        
+	strcpy(current->comm, "tDto");
+
+	init_waitqueue_head(&motCpciDomainWaitQ);
+
+	spin_lock_irqsave(&CpciPciAccessLock, flags);
+
+	for(;;) {
+		if (!motCpciDomainTakeBusNums) {
+			spin_unlock_irqrestore(&CpciPciAccessLock, flags);
+			interruptible_sleep_on(&motCpciDomainWaitQ);
+			spin_lock_irqsave(&CpciPciAccessLock, flags);
+		}
+
+		for (Bus = 0; Bus < CpciInfos->MaxBusNum; Bus++) {
+			if (motCpciDomainTakeBusNums & (0x1 << Bus)) {
+				motCpciDomainTakeBusNums &= ~(0x1 << Bus);
+				CpciDelBus(Bus, 0);
+			}
+		}
+	}
+}
+
+extern struct list_head pci_root_buses;
+extern struct pci_controller* hose_head;
+
+void
+motCpci_init(void)
+{
+	struct pci_bus *HeadBus;
+
+	/* Check to see if this is a hot swap and not a HA chassis. */
+	if (MotCpciNumSlots != NUM_HA_SLOTS) {
+		/* Set up to receive the ENUM signal. */
+		motEnum_init();
+
+		/* Export dependent function structure. */
+		CpciFunctions = &MotHsCpciFuncs;
+
+		/* Reset the hose and top level bus info to reality for HA numbers */
+		hose_head->last_busno = CpciBuses[0].LastBusNo;
+
+		HeadBus = pci_bus_b(pci_root_buses.next);
+		HeadBus->subordinate = CpciBuses[0].LastBusNo;
+
+		motCpci_find_driver(MOTHSC_BUSA);
+		return;
+	}
+
+	/* We now know this is an 82XX chassis so we need to be able
+	 * to catch the other host taking a bus domain away from this 
+	 * host.
+	 */
+	kernel_thread(motCpciCatchDomainTakeover, NULL,
+		      CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+
+	/* Initialize the hot swap controller. */
+	mot82XXhsc_init();
+
+	/* Export dependent function structure. */
+	CpciFunctions = &MotHaCpciFuncs;
+
+	/* Reset the hose and top level bus info to reality for HA numbers */
+	hose_head->last_busno = CpciBuses[1].LastBusNo;
+
+	HeadBus = pci_bus_b(pci_root_buses.next);
+	HeadBus->subordinate = CpciBuses[1].LastBusNo;
+
+	if (mot82XXhscBusStatus(MOTHSC_BUSA)) {
+		/* Bus was powered on at boot.  Need to allert 
+		 * system to download driver if needed. */
+		motCpci_find_driver(MOTHSC_BUSA);
+	}
+
+	if (mot82XXhscBusStatus(MOTHSC_BUSB)) {
+		/* Bus was powered on at boot.  Need to allert 
+		 * system to download driver if needed. */
+		motCpci_find_driver(MOTHSC_BUSB);
+	}
+}
+
+void
+motCpci_find_driver(int bus)
+{
+	struct pci_dev *Dev;
+	int Slot, LastSlot = -1, SlotSubDev = 0;
+
+	pci_for_each_dev(Dev) {
+		if ((Dev->bus->number >= CpciBuses[bus].FirstBusNo) &&
+		    (Dev->bus->number <= CpciBuses[bus].LastBusNo)) {
+
+			if ((Slot = CpciFindSlotFromDev(Dev)) < 0) {
+				continue;
+			}
+
+			if ((Dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+				continue;
+			}
+
+			if (Slot != LastSlot) {
+				LastSlot = Slot;
+		    		SlotSubDev = 0;
+			}
+
+			CpciFunctions->MapIrq(Dev);
+			Dev->cpci_location = (Slot << 16) | SlotSubDev++;
+
+			CpciRegisterOpenCheck(Dev);
+		}
+	}
+}
diff -u -r --new-file linux/drivers/ha/cpci/mot_enum.c ha/drivers/ha/cpci/mot_enum.c
--- linux/drivers/ha/cpci/mot_enum.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/mot_enum.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,599 @@
+/*
+ * mot_enum.c
+ *
+ * Motorola non HSC enum hardware access.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ */
+#include <linux/module.h>       
+#include <linux/kernel.h> 
+#include <linux/errno.h>        
+#include <linux/config.h>
+#include <linux/fs.h>           
+#include <linux/types.h>
+#include <linux/version.h>
+#include <linux/init.h> 
+#include <linux/slab.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/pci.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include <asm/delay.h>
+#include "mot_enum.h"
+#include "phs.h"
+
+/* Driver functions. */
+void motEnum_intr(int, void *, struct pt_regs *);
+
+int motEnumInit(void);
+int motEnumEnable(int, int);
+void motEnumDisable(void);
+void motEnumIntClear(void);
+BOOLEAN  motEnumInterruptCheck(void);
+BOOLEAN  motEnumQuery(void);
+
+int	  motEnumHsiInit(void);
+BOOLEAN	  motEnumHsiQueryEnumState(void);
+BOOLEAN	  motEnumHsiCheckEnumInterrupt(void *);
+HSI_STATUS motEnumHsiEnableEnums(void);
+HSI_STATUS motEnumHsiDisableEnums(void);
+int	  motEnumHsiConvertStatus(HSI_STATUS);
+
+/* Functions to be accessed from the PICMG 2.12 independent code */
+int  HsiThreadRegister(void);
+void HsiPlatformEnumHandler(int, void *, struct pt_regs *);
+
+#ifdef CONFIG_PPC
+#define ENUM_IRQ   9
+
+#define Z8536_BASE 0x844
+#define Z8536_DATA_A 0x844
+#define Z8536_DATA_B  0x845
+#define Z8536_DATA_C  0x846
+#define Z8536_CTL  0x847
+#define ZBUS_INT_ACK  0x84F
+#else
+#define ENUM_IRQ   11
+#endif
+
+int
+motEnum_init(void)
+{
+	printk("Initialize the Motorola Non HSC Enum controller\n");
+
+#ifdef CONFIG_PPC
+	if (check_region(Z8536_BASE, 8)) {
+		printk("Error allocating I/O space address 0x%x for enum handling\n", Z8536_BASE);
+		return -ENODEV;
+	}
+
+	request_region(Z8536_BASE, 4, "Enum");
+
+	if (request_irq(ENUM_IRQ, (void *)&motEnum_intr, SA_SHIRQ,
+			"Enum", &motEnum_init)) {
+		release_region(Z8536_BASE, 4);
+		return -EIO;
+	}
+#else
+	if (request_irq(ENUM_IRQ, (void *)&motEnum_intr, SA_SHIRQ,
+			"Enum", &motEnum_init)) {
+		return -EIO;
+	}
+#endif
+
+	/* If the PICMG 2.12 interface has been enabled then init it. */
+	if (motEnumHsiInit()) {
+		return -ESRCH;
+	}
+
+	HsiThreadRegister();
+
+	motEnumInit();
+
+	return 0;
+}
+
+void
+motEnum_intr(int irq, void *dev_id, struct pt_regs *regs)
+{
+	/* IF the PICMG 2.12 is configured then call its
+	 * interrupt routine.
+	 */
+	HsiPlatformEnumHandler(0, NULL, NULL);
+}
+
+#ifdef CONFIG_PPC
+
+/* some register definitions for the Zilog CIO */
+/* Master Interrupt Control Register */
+#define MASTER_INT_CTL	0x00
+
+#define MIC_MASTER_INT_ENABLE 0x80
+#define MIC_DISABLE_LOWER_CHAIN 0x40
+#define MIC_NO_VECTOR 0x20
+#define MIC_VECTOR_A_INCL_STS 0x10
+#define MIC_VECTOR_B_INCL_STS 0x08
+#define MIC_VECTOR_C_INCL_STS 0x04
+#define MIC_RIGHT_JUSTIFIED_ADDR 0x02
+#define MIC_RESET 0x01
+
+/* Master Configuration Control Register */ 
+#define MAIN_CC		0x01
+
+#define MCC_PORT_B_ENABLE 0x80
+#define MCC_CNTR_1_ENABLE 0x40
+#define MCC_CNTR_2_ENABLE 0x20
+#define MCC_PORT_C_ENABLE 0x10
+#define MCC_PORT_A_B_LINK 0x08
+#define MCC_PORT_A_ENABLE 0x04
+#define MCC_CNTR_MODE_MASK 0x03
+
+/* Interrupt Vector Registers */
+#define PORT_A_IV	0x02
+#define PORT_B_IV	0x03
+#define PORT_C_IV	0x04
+
+#define PORTB_CS	0x9
+
+#define PORTA_DR	0xd
+#define PORTB_DR	0xe
+#define PORTC_DR	0xf
+
+#define CURRENT_VECTOR 0x1f
+
+#define PORTA_MS	0x20
+#define PORTB_MS	0x28
+
+#define PORTB_DPP	0x2a
+#define PORTB_DD	0x2b
+#define PORTB_SIO	0x2c
+#define PORTB_PP	0x2d
+#define PORTB_PT	0x2e
+#define PORTB_PM	0x2f
+
+#define INTR_CLR	0x20
+#define INTR_SET	0xc0
+
+#define MAIN_LAT_PM	0x1
+#define MAIN_OR_MODE	0x04
+
+#define ENUM_BIT	0x40	/* Bit 6 */
+#define INT_PEND	0x20	/* Bit 5 */
+#define PATTERN_MATCH_FLAG 0x02 /* Bit 1 of PORTx_CS register */
+
+#define MOT_ENUM_IN_CTL() inb(Z8536_CTL); eieio()
+#define MOT_ENUM_OUT_CTL(x) outb((x),Z8536_CTL); eieio(); udelay(2)
+
+static volatile unsigned int 
+read_z8536( unsigned char reg )
+{
+	uint temp;
+	
+	(void) inb( Z8536_CTL ); //set state machine to known state
+	outb( reg, Z8536_CTL); // point to the register
+	temp = inb( Z8536_CTL ); // get register value
+	
+	return temp;
+}
+
+static void
+write_z8536( unsigned char reg, unsigned char val )
+{
+	(void) inb(Z8536_CTL); //set state machine to known state
+	outb( reg, Z8536_CTL ); // point to the register and arm write
+	outb( val, Z8536_CTL ); // do data transfer to the target register
+
+	return;
+}
+
+int
+motEnumInit(void)
+{
+	unsigned int RetVal;
+	unsigned long flags;
+
+	/* Disable Port B in Config Control Reg */
+	RetVal = read_z8536( MAIN_CC );
+	write_z8536( MAIN_CC, (RetVal & ~MCC_PORT_B_ENABLE) );
+	(void) read_z8536( MAIN_CC );
+	(void) read_z8536( PORTB_DR );
+
+	/* now setup some interrupt pseudo-vectors for this part */
+	if ( 0 == read_z8536( PORT_A_IV ) )
+		{
+		write_z8536( PORT_A_IV, 0xa0 );
+		(void) read_z8536( PORT_A_IV );
+		}
+	
+	if ( 0 == read_z8536( PORT_B_IV ) )
+		{
+		write_z8536( PORT_B_IV, 0xb0 );
+		(void) read_z8536( PORT_B_IV );
+		}
+	else
+		{
+		write_z8536( PORT_B_IV, 0xb0 );
+		(void) read_z8536( PORT_B_IV );
+		}
+	
+	if ( 0 == read_z8536( PORT_C_IV ) )
+		{
+		write_z8536( PORT_C_IV, 0xc0 );
+		(void) read_z8536( PORT_C_IV );
+		}
+	
+
+	/* Port Mode */
+	write_z8536(PORTB_MS, MAIN_OR_MODE); // set as bit port with pattern or
+	(void) read_z8536( PORTB_MS );
+	(void) read_z8536( PORTB_DR );
+
+	/* Set pattern transition for zero */
+	RetVal = read_z8536( PORTB_PM );
+	write_z8536( PORTB_PM, (RetVal | ENUM_BIT) ); // enable pattern on enum bit
+	(void) read_z8536( PORTB_PM );
+	(void) read_z8536( PORTB_DR );
+
+	RetVal = read_z8536( PORTB_PT );
+	write_z8536( PORTB_PT, (RetVal & ~ENUM_BIT) ); // set for level, not transition
+	(void) read_z8536( PORTB_PT );
+	(void) read_z8536( PORTB_DR );
+
+	RetVal = read_z8536( PORTB_PP );
+	write_z8536( PORTB_PP, (RetVal & ~ENUM_BIT) ); // look for zero level
+	(void) read_z8536( PORTB_PP );
+	(void) read_z8536( PORTB_DR );
+
+	/* set up PortB enum bit data path */
+	RetVal = read_z8536( PORTB_DPP );
+	write_z8536( PORTB_DPP, (RetVal & ~ENUM_BIT) ); // set data path to normal
+	(void) read_z8536( PORTB_DPP );
+	(void) read_z8536( PORTB_DR );
+
+	RetVal = read_z8536( PORTB_DD );
+	write_z8536( PORTB_DD, (RetVal | ENUM_BIT) ); // set input for enum bit
+	(void) read_z8536( PORTB_DD );
+	(void) read_z8536( PORTB_DR );
+
+	RetVal = read_z8536( PORTB_SIO );
+	write_z8536( PORTB_SIO, (RetVal & ~ENUM_BIT) ); // turn off the ones catcher
+	(void) read_z8536( PORTB_SIO );
+	(void) read_z8536( PORTB_DR );
+
+	/* Enable Port B in Config Control Reg */
+	RetVal = read_z8536( MAIN_CC );
+	write_z8536( MAIN_CC, (RetVal | MCC_PORT_B_ENABLE) );
+	(void) read_z8536( MAIN_CC );
+	(void) read_z8536( PORTB_DR );
+
+	/* Set interrupt enable for port B */
+	RetVal = read_z8536( PORTB_CS );
+	write_z8536( PORTB_CS, INTR_SET );
+	(void) read_z8536( PORTB_CS );
+	(void) read_z8536( PORTB_DR );
+
+	/* Set master interrupt enable */
+	RetVal = read_z8536( MASTER_INT_CTL );
+
+	save_flags( flags ); // debug - so state prior to interrupt prints
+	cli();
+
+	write_z8536( MASTER_INT_CTL,
+		     ( RetVal | MIC_MASTER_INT_ENABLE | MIC_VECTOR_B_INCL_STS ) );
+	(void) read_z8536( MASTER_INT_CTL );
+	(void) read_z8536( PORTB_DR );
+	(void) read_z8536( CURRENT_VECTOR );
+
+	restore_flags( flags );
+
+	return 0;
+}
+
+int
+motEnumEnable(int bus, int flag)
+{
+	unsigned int RetVal;
+	unsigned long flags;
+
+	if (bus != 0) {
+		return -EINVAL;
+	}
+
+	/* Disable Port B in Config Control Reg */
+	RetVal = read_z8536( MAIN_CC );
+	write_z8536( MAIN_CC, (RetVal & ~MCC_PORT_B_ENABLE) );
+
+	/* Set pattern transition back to 1. */
+	(void) read_z8536( PORTB_CS );
+	RetVal = read_z8536( PORTB_PM );
+	write_z8536( PORTB_PM, (RetVal | ENUM_BIT) ); // enable pattern on enum bit
+	(void) read_z8536( PORTB_PM );
+	(void) read_z8536( PORTB_DR );
+	(void) read_z8536( PORTB_CS );
+
+	/* Enable Port B in Config Control Reg */
+	save_flags( flags );
+	cli();
+	RetVal = read_z8536( MAIN_CC );
+	write_z8536( MAIN_CC, (RetVal | MCC_PORT_B_ENABLE) );
+	(void) read_z8536( CURRENT_VECTOR );
+	restore_flags( flags );
+
+	return 0;
+}
+
+void
+motEnumDisable(void)
+{
+	unsigned int RetVal;
+
+	/* Set pattern transition mode to 0 mask enum off. */
+	(void) read_z8536( PORTB_CS );
+	RetVal = read_z8536( PORTB_PM );
+	write_z8536( PORTB_PM, (RetVal & ~ENUM_BIT) ); // disable pattern on enum bit
+	(void) read_z8536( PORTB_PM );
+	(void) read_z8536( PORTB_DR );
+	(void) read_z8536( PORTB_CS );
+	motEnumIntClear();
+
+	return;
+}
+
+void
+motEnumIntClear(void)
+{
+	(void) read_z8536( PORTB_CS );
+	write_z8536( PORTB_CS, INTR_CLR ); // clear the pending interrupt indication
+	(void) read_z8536( PORTB_DR );
+	(void) read_z8536( PORTB_CS );
+
+	return;
+}
+
+int b_direct = 0;
+int old_aval = 0;
+int old_bval = 0;
+int old_cval = 0;
+
+BOOLEAN
+motEnumInterruptCheck(void)
+{
+	unsigned int RetVal;
+
+	RetVal = read_z8536( PORTB_CS );
+
+	return ( (RetVal & (INT_PEND|PATTERN_MATCH_FLAG))==(INT_PEND|PATTERN_MATCH_FLAG));
+}
+
+BOOLEAN
+motEnumQuery(void)
+{
+	unsigned int RetVal;
+
+	RetVal = read_z8536( PORTB_DR );
+
+	if ( (~RetVal) & ENUM_BIT)
+		{
+		return TRUE;
+		}
+	else
+		{
+		return FALSE;
+		}
+
+}
+
+#else /* PPC_CONFIG */
+
+#define ENUM_DEV_SELECT	  0x0f
+
+#define ENUM_STAT	  0x00
+#define ENUM_INT_SELECT	  0x04
+#define ENUM_INT_ENABLE	  0x07
+#define ENUM_LATCH_ENABLE 0x09
+
+#define ENUM_ENABLE_INT	  0x90
+#define ENUM_RESET_LATCH  0x10
+
+#define FPGA_INDEX 0x5d
+#define FPGA_DATA 0x5f
+
+#define FPGA_OUT(reg, data) outb(reg, FPGA_INDEX); \
+			    outb(data, FPGA_DATA)
+
+#define FPGA_IN(reg, data) outb(reg, FPGA_INDEX); \
+			   data = inb(FPGA_DATA)
+
+int
+motEnumInit(void)
+{
+	unsigned char IntEnableReg;
+
+	FPGA_OUT(ENUM_DEV_SELECT, 0x00);	/* Select legacy device */
+	FPGA_OUT(ENUM_INT_SELECT, ENUM_IRQ);	/* Set signal to generate */
+	
+	/* Clear the latch on the ENUM if set */
+	FPGA_OUT(ENUM_LATCH_ENABLE, ENUM_RESET_LATCH);
+
+	/* Enable IRQ */
+	FPGA_IN(ENUM_INT_ENABLE, IntEnableReg);
+	FPGA_OUT(ENUM_INT_ENABLE, IntEnableReg | ENUM_ENABLE_INT);
+
+	return 0;
+}
+
+int
+motEnumEnable(int bus, int flag)
+{
+	unsigned char IntEnableReg;
+
+	FPGA_OUT(ENUM_DEV_SELECT, 0x00);	/* Select legacy device */
+
+	/* Clear the latch on the ENUM if set */
+	FPGA_OUT(ENUM_LATCH_ENABLE, ENUM_RESET_LATCH);
+
+	/* Disable IRQ */
+	FPGA_IN(ENUM_INT_ENABLE, IntEnableReg);
+	FPGA_OUT(ENUM_INT_ENABLE, IntEnableReg | ENUM_ENABLE_INT);
+
+	return 0;
+}
+
+void
+motEnumDisable(void)
+{
+	motEnumIntClear();
+	return;
+}
+
+void
+motEnumIntClear(void)
+{
+	unsigned char IntEnableReg;
+
+	FPGA_OUT(ENUM_DEV_SELECT, 0x00);	/* Select legacy device */
+
+	/* Clear the latch on the ENUM if set */
+	FPGA_OUT(ENUM_LATCH_ENABLE, ENUM_RESET_LATCH);
+
+	/* Disable IRQ */
+	FPGA_IN(ENUM_INT_ENABLE, IntEnableReg);
+	FPGA_OUT(ENUM_INT_ENABLE, IntEnableReg & ~ENUM_ENABLE_INT);
+
+	return;
+}
+
+BOOLEAN
+motEnumQuery(void)
+{
+	unsigned char EnumStat;
+
+	/* Clear the latch on the ENUM if set */
+	FPGA_OUT(ENUM_LATCH_ENABLE, ENUM_RESET_LATCH);
+
+	FPGA_IN(ENUM_STAT, EnumStat);
+
+	/* Set means no enum. */
+	if (EnumStat & 0x10) {
+		return FALSE;
+	} else {
+		return TRUE;
+	}
+}
+
+#endif /* CONFIG_PPC */
+
+static HSI_INIT initData;
+
+int
+motEnumHsiInit(void)
+{
+	HSI_STATUS status;
+	void * pExt;
+	struct tq_struct noDpc;
+
+	/* Initialize the PICMG 2.12 Driver */
+	noDpc.sync = 0;
+	noDpc.routine = NULL;
+	noDpc.data = NULL;
+
+	initData.DevExtSize = 0;
+	initData.Intr = 0;
+	initData.IntrFlags = 0;
+	initData.pDevId = NULL;
+	initData.QueryEnumState = motEnumHsiQueryEnumState;
+	initData.CheckEnumInterrupt = motEnumHsiCheckEnumInterrupt;
+	initData.Enable = motEnumHsiEnableEnums;
+	initData.Disable = motEnumHsiDisableEnums;
+	initData.Isr = (INTERRUPT_SERVICE_ROUTINE) NULL;
+	initData.Dpc = noDpc;
+
+	if ((status = HsiPlatformInitialize(&initData, &pExt)) != 0) {
+		return motEnumHsiConvertStatus(status);
+	}
+	return HSI_STATUS_SUCCESS;
+}
+
+BOOLEAN
+motEnumHsiQueryEnumState(void)
+{
+	return motEnumQuery();
+}
+
+BOOLEAN
+motEnumHsiCheckEnumInterrupt(void *pDeviceId)
+{
+#ifdef CONFIG_PPC
+	return motEnumInterruptCheck();
+
+#else
+	return (pDeviceId == hsi_platform_data.pDevId);
+#endif /* CONFIG_PPC */
+
+}
+
+HSI_STATUS
+motEnumHsiEnableEnums(void)
+{
+	motEnumEnable(0, 0);
+	return HSI_STATUS_SUCCESS;
+}
+
+HSI_STATUS
+motEnumHsiDisableEnums(void)
+{
+	motEnumDisable();
+	return HSI_STATUS_SUCCESS;
+}
+
+int
+motEnumHsiConvertStatus(HSI_STATUS status)
+{
+	switch (status) {
+	case HSI_STATUS_SUCCESS :
+		return 0;
+	case HSI_STATUS_NO_MEMORY :
+		return -ENOMEM;
+	case HSI_STATUS_INVALID_PARAMETER :
+		return -EINVAL;
+	case HSI_STATUS_NOT_IMPLEMENTED :
+		return -ENOSYS;
+	case HSI_STATUS_NO_SUCH_DEVICE :
+		return -ENODEV;
+	case HSI_STATUS_NO_DATA_DETECTED :
+		return -ENODATA;
+	case HSI_STATUS_OPERATION_NOT_APPLICABLE :
+		return -EPERM;
+	case HSI_STATUS_NOT_AVAILABLE :
+		return -EBUSY;
+	default :
+		return -EPERM;     // HSI_STATUS_FAILURE goes here too
+	}
+}
diff -u -r --new-file linux/drivers/ha/cpci/mot_enum.h ha/drivers/ha/cpci/mot_enum.h
--- linux/drivers/ha/cpci/mot_enum.h	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/mot_enum.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,42 @@
+/*
+ * mot_enum.h
+ *
+ * Header file for access to the Motorola non HSC enum hardware access.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ */
+
+#ifndef MOT_ENUM_H
+#define MOT_ENUM_H
+
+int motEnum_init(void);
+int motEnumEnable(int, int);
+
+
+#endif /* MOT_ENUM_H */
diff -u -r --new-file linux/drivers/ha/cpci/pdphs_zt5550.c ha/drivers/ha/cpci/pdphs_zt5550.c
--- linux/drivers/ha/cpci/pdphs_zt5550.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/pdphs_zt5550.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,460 @@
+/*
+ * pdphs_zt5550.c
+ *
+ * Ziatech 5550 Platform dependent routines for PICMG 2.12 compatible hot swap.
+ *
+ * Author: MontaVista Software, Inc.
+ *         support@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ * 2001Mar02 jfm - Added most of the platform-specific stuff for ZT5550
+ * 2000Nov08 jfm - Original Version
+ */
+
+#include <linux/errno.h>
+#include <linux/pci.h>
+#include <linux/tqueue.h>
+#include <asm/page.h>
+#include <asm/signal.h>
+
+#include "phs.h"
+#include "phs_zt5550.h"
+
+
+/*
+ * Prototype:
+ * HSI_STATUS ZT5550_config (
+ *     OUT SATURN_PARAMS *hcDevice );
+ * 
+ * Arguments:
+ * hcDevice - The struct containing register numbers for the registers
+ *	which are used in the host controller
+ *
+ * Return Value:
+ * HSI_STATUS_SUCCESS - registers were successfully retrieved
+ * HSI_STATUS_NO_SUCH_DEVICE - The host controller was not found
+ * HSI_STATUS_NO_MEMORY - The host controller could not be mapped in
+ * 
+ * Synopsis:
+ * This routine returns the configuration data for the ZT5550 host 
+ * controller, along with the addresses of the host controller 
+ * configuration and status registers.
+ *
+ * NOTE that the SATURN_PARAMS struct is a subset of the SATURN_HC_PARAMS
+ * struct used by the full RSS driver.  The field names remain the same,
+ * so that the base code need not be changed if this is merged with the
+ * RSS driver.
+ *
+ * Algorithm:
+ * First, find the host controller in PCI space, then retrieve the data.
+ *
+ */
+
+HSI_STATUS ZT5550_config (
+    OUT SATURN_PARAMS *hcDevice )
+{
+    unsigned long ioBase;
+    unsigned long memBase;
+    struct pci_dev * pci_device;
+    uint32 intReg;	/* Interrupt mask register address */
+
+/* look for first device matching vendor and device IDs */
+
+    if (!(pci_device = pci_find_device(ZIATECH_VENDOR_ID, 
+		ZT5550_HOSTCNTRL_DEVICE_ID, NULL))) {
+	return HSI_STATUS_NO_SUCH_DEVICE;
+    }
+
+    /* the low order bits of the address base registers
+     * must be masked out.  */
+
+    ioBase = pci_resource_start(pci_device, 0) & PCI_IOBASE_MASK;
+    memBase = pci_resource_start(pci_device, 1) & PCI_MEMBASE_MASK;
+
+/*
+ * Get access to I/O addresses.  Note that the size is the highest
+ * address which will be read.  Since things are page aligned and
+ * only entire pages are mapped, you should not need to add anything.
+ */
+
+    if (hcDevice->baseAddrPtr) {
+		iounmap((void*)hcDevice->baseAddrPtr);
+    }
+
+    if (!(hcDevice->baseAddrPtr = (uint32)ioremap(memBase, PAGE_SIZE))) {
+		return HSI_STATUS_NO_MEMORY;
+    }
+
+    hcDevice->pci.bus = pci_device->bus->number;
+    hcDevice->pci.device = PCI_SLOT(pci_device->devfn);
+    hcDevice->pci.function = PCI_FUNC(pci_device->devfn);
+
+    hcDevice->intLevel = pci_device->irq;
+
+    hcDevice->csr_hcindex = hcDevice->baseAddrPtr + 0x00;
+    hcDevice->csr_hcdata =  hcDevice->baseAddrPtr + 0x04;
+    hcDevice->csr_intstat = hcDevice->baseAddrPtr + 0x08;
+    hcDevice->csr_intmask = hcDevice->baseAddrPtr + 0x09;
+
+/*
+ * Disable host control, fault and serial interrupts
+ */
+	intReg = hcDevice->csr_hcindex;
+	writeb((uint8)0x08,intReg);
+	intReg = hcDevice->csr_hcdata;
+	writeb((uint8)0x07,intReg);
+
+/*
+ * Disable timer0, timer1 and ENUM interrupts
+ */
+	intReg = hcDevice->csr_intmask;
+	writeb((uint8)0x07,intReg);
+
+    return HSI_STATUS_SUCCESS;
+}
+
+/*
+ * Prototype: 
+ * int convert_status ( 
+ *	IN HSI_STATUS status ); 
+ *
+ * Arguments: 
+ * status - the HSI_STATUS value to convert 
+ *
+ * Return Value: 
+ * The equivalent errno for the status value
+ *
+ * Synopsis: 
+ * Converts an HSI_STATUS value to the equivalent Linux errno
+ *
+ * Algorithm:
+ * It's just a giant switch statement
+ *
+ */
+
+int convert_status (
+    IN HSI_STATUS status)
+{
+    switch (status) {
+	case HSI_STATUS_SUCCESS :
+	    return 0;
+	case HSI_STATUS_NO_MEMORY :
+	    return -ENOMEM;
+	case HSI_STATUS_INVALID_PARAMETER :
+	    return -EINVAL;
+	case HSI_STATUS_NOT_IMPLEMENTED :
+	    return -ENOSYS;
+	case HSI_STATUS_NO_SUCH_DEVICE :
+	    return -ENODEV;
+	case HSI_STATUS_NO_DATA_DETECTED :
+	    return -ENODATA;
+	case HSI_STATUS_OPERATION_NOT_APPLICABLE :
+	    return -EPERM;
+	case HSI_STATUS_NOT_AVAILABLE :
+	    return -EBUSY;
+	default :
+	    return -EPERM;     // HSI_STATUS_FAILURE goes here too
+    }
+}
+
+/*
+ * Prototype: 
+ * int ZT5550_init ( 
+ *	void); 
+ *
+ * Arguments: 
+ * none 
+ *
+ * Return Value: 
+ * 0 - module installation succeeded 
+ * <0 - error code from errno.h 
+ *
+ * Synopsis: 
+ * This is the init_module routine called by the kernel when the module 
+ * is installed.  It initializes the platform data structures.
+ *
+ * Algorithm:
+ * Get the parameters out of PCI Configuration Space, then call
+ * HsiPlatformInitialize
+ *
+ */
+
+int
+ZT5550_init (
+    void)
+{
+    HSI_INIT initData;
+    HSI_STATUS status;
+    SATURN_PARAMS hcDevice;
+    void * pExt;
+    struct tq_struct noDpc;
+
+//
+//  Initialize the initData struct
+//
+
+/*
+ * There is kind of a chicken/egg problem here, in that you must
+ * have the device specific information to initialize the platform,
+ * but the allocation of the device specific data area is done
+ * during platform initialization.  Rather than spoof it, we 
+ * create the initial struct on the stack, and then copy it to
+ * the allocated area after platform initialization.
+ */
+
+    status = ZT5550_config(&hcDevice);       // Get Host Controller specifics
+
+    if (status != HSI_STATUS_SUCCESS) {
+	return convert_status(status);
+    }
+
+    noDpc.sync = 0;
+    noDpc.routine = NULL;
+    noDpc.data = NULL;
+
+    initData.DevExtSize = sizeof(hcDevice);  // platform specific data area
+    initData.Intr = hcDevice.intLevel;       // irq requested by config space
+    initData.IntrFlags = SA_SAMPLE_RANDOM;   // ENUM# interrupts are random
+//*    initData.IntrFlags = SA_SHIRQ;   // ENUM# interrupts are random
+    initData.pDevId = NULL;		     // irq not shared
+//*    initData.pDevId = &EnableRoutine;
+    initData.QueryEnumState = QueryEnumStateRoutine;
+    initData.CheckEnumInterrupt = CheckEnumInterruptRoutine;
+    initData.Enable = EnableRoutine;
+    initData.Disable = DisableRoutine;
+    initData.Isr = (INTERRUPT_SERVICE_ROUTINE) NULL;
+    initData.Dpc = noDpc;
+
+    status = HsiPlatformInitialize(&initData, &pExt);
+
+    if (status != HSI_STATUS_SUCCESS) {
+	return convert_status(status);
+    }
+
+	/* copy the platform specific data */
+    *(SATURN_PARAMS *)hsi_instance_data = hcDevice;    
+    return HSI_STATUS_SUCCESS;
+}
+
+/*
+ * Prototype: void cleanup_module 
+ *   ( void);
+ *
+ * Arguments:
+ * none
+ *
+ * Return Value:
+ * none
+ *
+ * Synopsis:
+ * This is the cleanup_module routine called by the kernel when the 
+ * module is removed. It is responsible for returning all system 
+ * resources allocated by the Platform Driver in preparation for 
+ * unloading the module. Most implementations will just call the 
+ * platform-independent function HsiPlatformTerminate() from this 
+ * routine.
+ *
+ */
+
+module_init(ZT5550_init);
+module_exit(HsiPlatformTerminate);
+
+
+/*
+ * Prototype:
+ * BOOLEAN QueryEnumStateRoutine (
+ *     void );
+ *
+ * Arguments:
+ * none
+ *
+ * Return Value:
+ * TRUE   if ENUM# is active
+ * FALSE  if ENUM# is inactive
+ *
+ * Synopsis:
+ * This function returns the current state of the hardware signal ENUM# 
+ * on the CPci backplane. It is independent of whether ENUM# interrupts
+ * are currently masked on the system board.
+ *
+ * Algorithm: Read the state of the ENUM# signal from the IO port.
+ *
+ */
+
+BOOLEAN QueryEnumStateRoutine (
+    void )
+{
+    uint8 IOdata;
+
+    /* read the I/O port containing ENUM# */
+    IOdata = inb_p(ZT5550_PortNum);
+
+    /* is ENUM# asserted? */
+    return ((IOdata & ZT5550_EnumMask) == ZT5550_EnumMask);
+}
+
+/*
+ * Prototype:
+ * BOOLEAN CheckEnumInterruptRoutine (
+ *     IN void *pDeviceID );
+ *
+ * Arguments:
+ * pDeviceID - The interrupting device ID sent in from the interrupt 
+ *     dispatcher.
+ *
+ * Return Value:
+ * TRUE   if the current interrupt was caused by the ENUM# signal
+ * FALSE   otherwise
+ *
+ * Synopsis:
+ * This function verifies that the current interrupt was caused by 
+ * the ENUM# signal. It is only necessary to call this function if
+ * the ENUM# IRQ is shared.  
+ *
+ * Algorithm:
+ * Check to see if the device ID passed in is the one used when
+ * registering the ENUM# interrupt handler.
+ * NOTE that no check is made whether the interrupt is shared, but
+ * this algorithm should work in any case.
+ */
+
+BOOLEAN CheckEnumInterruptRoutine (
+    void *pDeviceId)
+{
+BOOLEAN ret;
+SATURN_PARAMS *hcDevice = (SATURN_PARAMS *)hsi_instance_data;
+uint32 intReg;	/* Interrupt status register address */
+uint8 reg;
+
+	ret = FALSE;
+    if (pDeviceId == hsi_platform_data.pDevId) {
+			intReg = hcDevice->csr_intstat;
+			reg = readb(intReg);
+			if (reg)
+				ret = TRUE;
+	}
+    return ret;
+}
+
+/*
+ * Prototype:
+ * HSI_STATUS EnableRoutine (
+ *     void);
+ *
+ * Arguments:
+ * none
+ *
+ * Return Value:
+ * HSI_STATUS_SUCCESS		ENUM# events have been enabled
+ * HSI_STATUS_FAILURE		ENUM# events were already enabled
+ * HSI_STATUS_NOT_IMPLEMENTED	ENUM# events are not supported by this platform
+ * Other HSI_STATUS values	Other errors occurred during execution of this
+ * 				function
+ *
+ * Synopsis:
+ * This function enables the generation of ENUM# events. It is typically
+ * called by the platform-independent part after handling an ENUM# event
+ * to re-enable ENUM# events.
+ *
+ * Implementation of this function is optional.
+ *
+ * Algorithm:
+ * Write the control register masking ENUM# interrupts to unmask ENUM#.
+ *
+ */
+
+HSI_STATUS EnableRoutine (
+    void )
+{
+    uint8 reg;		/* temporary holding area */
+    uint32 intReg;	/* Interrupt mask register address */
+    SATURN_PARAMS *hcDevice = (SATURN_PARAMS *)hsi_instance_data;
+
+    if(hcDevice == NULL) {
+	return HSI_STATUS_NOT_AVAILABLE;
+    }
+
+    intReg = hcDevice->csr_intmask;
+    
+    reg = readb(intReg);	// read the interrupt mask register
+    if (!(reg & ZT5550_EnumEnableBit)) {
+	return HSI_STATUS_FAILURE;  // ENUM# ints already enabled
+    }
+
+    reg = reg & ~ZT5550_EnumEnableBit;
+    writeb(reg, intReg);	// write the new interrupt mask out
+
+    return HSI_STATUS_SUCCESS;
+}
+
+/*
+ * Prototype:
+ * HSI_STATUS DisableRoutine (
+ *     void);
+ *
+ * Arguments:
+ * none
+ *
+ * Return Value:
+ * HSI_STATUS_SUCCESS		ENUM# events have been enabled
+ * HSI_STATUS_FAILURE		ENUM# events were already enabled
+ * HSI_STATUS_NOT_IMPLEMENTED	ENUM# events are not supported by this platform
+ * Other HSI_STATUS values	Other errors occurred during execution of this
+ * 				function
+ *
+ * Synopsis:
+ * This function disables the generation of ENUM# events. It is typically
+ * called by the platform-independent ISR when handling an ENUM# interrupt.
+ *
+ * Implementation of this function is optional.
+ *
+ * Algorithm:
+ * Write the control register masking ENUM# interrupts to mask ENUM#.
+ *
+ */
+
+HSI_STATUS DisableRoutine (
+    void )
+{
+    uint8 reg;		/* temporary holding area */
+    uint32 intReg;	/* Interrupt mask register address */
+    SATURN_PARAMS *hcDevice = (SATURN_PARAMS *)hsi_instance_data;
+
+    if(hcDevice == NULL) {
+	return HSI_STATUS_NOT_AVAILABLE;
+    }
+
+    intReg = hcDevice->csr_intmask;
+    
+    reg = readb(intReg);	// read then interrupt mask register
+    if (reg & ZT5550_EnumEnableBit) {
+	return HSI_STATUS_FAILURE;  // ENUM# ints already disabled
+    }
+
+    reg = reg | ZT5550_EnumEnableBit;
+    writeb(reg, intReg);	// write the new interrupt mask out
+
+    return HSI_STATUS_SUCCESS;
+}
diff -u -r --new-file linux/drivers/ha/cpci/phs.h ha/drivers/ha/cpci/phs.h
--- linux/drivers/ha/cpci/phs.h	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/phs.h	Thu Dec 13 13:25:22 2001
@@ -0,0 +1,377 @@
+/*
+ * phs.h
+ *
+ * Include file for PICMG compatible hot swap operations
+ *
+ * Author: MontaVista Software, Inc.
+ *         support@mvista.com
+ *
+ * Copyright 2000 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ * 2000Oct30 jfm - Original Version
+ */
+
+#ifndef LINUX_PICMG_HOTSWAP_H
+#define LINUX_PICMG_HOTSWAP_H
+
+// the macros IN and OUT are used to help comprehension in 
+// the following function prototypes, and have no other purpose
+#define IN
+#define OUT
+
+#define FALSE 0
+#define TRUE !FALSE
+
+// OS-dependent types used by the PICMG 2.12 spec.
+#include <linux/types.h>
+#include <linux/fs.h>
+#include <linux/tqueue.h>
+#include <asm/ptrace.h>
+
+typedef __s8 int8;
+typedef __s16 int16;
+typedef __s32 int32;
+typedef __u8 uint8;
+typedef __u16 uint16;
+typedef __u32 uint32;
+typedef struct file HSI_DEVICE;
+typedef struct file * HSI_SLOT_CONTROL_HANDLE;
+typedef int BOOLEAN;
+typedef int HSI_STATUS;
+
+// Main Function table definition 
+typedef void (*PLATFORM_ENUM_EVENT_CALLBACK)( 
+	IN void *pContext );
+
+typedef BOOLEAN (*QUERY_ENUM_STATE_ROUTINE)( 
+	IN HSI_DEVICE *pDevice ); 
+
+typedef HSI_STATUS (*SET_ENUM_EVENT_CALLBACK)( 
+	IN HSI_DEVICE *pDevice, 
+	IN PLATFORM_ENUM_EVENT_CALLBACK Callback, 
+	IN void *pContext ); 
+
+typedef BOOLEAN (*ENABLE_ENUM_ROUTINE)( 
+	IN HSI_DEVICE *pDevice, 
+	IN BOOLEAN State );
+
+typedef struct HSI_PLATFORM_FTABLE_STRUCT { 
+	// Function table header 
+	uint16 Version; 
+	uint16 Size; 
+	QUERY_ENUM_STATE_ROUTINE QueryEnumStateFunc; 
+	SET_ENUM_EVENT_CALLBACK SetEnumEventCallbackFunc; 
+	ENABLE_ENUM_ROUTINE EnableEnumEventsFunc; 
+} HSI_PLATFORM_FTABLE; 
+
+BOOLEAN QueryEnumState( 
+	IN HSI_DEVICE *pDevice );
+
+HSI_STATUS SetEnumEventCallback( 
+	IN HSI_DEVICE *pDevice, 
+	IN PLATFORM_ENUM_EVENT_CALLBACK Callback, 
+	IN void *pContext );
+
+BOOLEAN EnableEnumEvents( 
+	IN HSI_DEVICE *pDevice, 
+	IN BOOLEAN State );
+
+//
+// HS_CSR definitions
+//
+
+typedef struct HSI_SLOT_CONFIG_INTERFACE_STRUCT HSI_SLOT_CONFIG_INTERFACE;
+
+typedef int32 (*READ_CONFIG_ROUTINE) ( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *Buffer, 
+	IN uint32 Offset, 
+	IN uint32 Size ); 
+
+typedef int32 (*WRITE_CONFIG_ROUTINE) ( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *Buffer, 
+	IN uint32 Offset, 
+	IN uint32 Size );
+
+int32 ReadConfigRoutine( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	OUT void *Buffer, 
+	IN uint32 Offset, 
+	IN uint32 Size );
+
+int32 WriteConfigRoutine( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *Buffer, 
+	IN uint32 Offset, 
+	IN uint32 Size );
+
+struct HSI_SLOT_CONFIG_INTERFACE_STRUCT { 
+	uint16 Version; 
+	uint16 Size;	// Should be sizeof(HSI_SLOT_CONFIG_INTERFACE)
+	READ_CONFIG_ROUTINE ReadConfig; // Function to read config space
+	WRITE_CONFIG_ROUTINE WriteConfig; // Function to write config space 
+	// Other private fields go here 
+};
+
+// Function pointer typedefs for handling alternative HS_CSR operations 
+
+typedef HSI_STATUS (*OPEN_HS_CSR_FUNCTION)( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	OUT void **ppContext ); 
+
+typedef HSI_STATUS (*CLOSE_HS_CSR_FUNCTION)( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext ); 
+
+typedef HSI_STATUS (*GET_HS_CSR_FUNCTION)( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext, 
+	OUT uint8 *pResult ); 
+
+typedef HSI_STATUS (*SET_HS_CSR_FUNCTION)( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext, 
+	IN uint8 Mask ); 
+
+typedef HSI_STATUS (*CLEAR_HS_CSR_FUNCTION)( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext, 
+	IN uint8 Mask );  
+
+// Function table for handling HS_CSR operations 
+typedef struct HSI_HSCSR_FTABLE_STRUCT {
+	// Function table header 
+	uint16 Version; 
+	uint16 Size; // Should be sizeof(HSI_HSCSR_FTABLE) 
+	uint32 VendorID; // Board descriptor: Vendor ID 
+	uint32 DeviceID; // Board descriptor: Device ID 
+	uint32 SubVendorID; // Board descriptor: Subsystem Vendor ID 
+	uint32 SubSystemID; // Board descriptor: Subsystem ID 
+	uint8 StartRevID; // Board descriptor: starting Revision ID 
+	uint8 EndRevID; // Board descriptor: ending Revision ID 
+	// The function table 
+	OPEN_HS_CSR_FUNCTION OpenHsCsr; // Open function 
+	CLOSE_HS_CSR_FUNCTION CloseHsCsr; // Close function 
+	GET_HS_CSR_FUNCTION GetHsCsrBits; // Get bits function 
+	SET_HS_CSR_FUNCTION SetHsCsrBits; // Set bits function 
+	CLEAR_HS_CSR_FUNCTION ClearHsCsrBits; // Clear bits function 
+} HSI_HSCSR_FTABLE;
+
+HSI_STATUS OpenHsCsrRoutine( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	OUT void **ppContext );
+
+HSI_STATUS CloseHsCsrRoutine( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext );
+
+HSI_STATUS GetHsCsrBitsRoutine( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext, 
+	OUT uint8 *pResult );
+
+HSI_STATUS SetHsCsrBitsRoutine( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext, 
+	IN uint8 Mask );
+
+HSI_STATUS ClearHsCsrBitsRoutine( 
+	IN HSI_SLOT_CONFIG_INTERFACE *pSlotInterface, 
+	IN void *pContext, 
+	IN uint8 Mask );
+
+HSI_STATUS HsiRegisterAlternateCsrHandler( 
+	IN HSI_HSCSR_FTABLE *pFtable );
+
+//
+// High Availailability Slot Control definitions
+//
+HSI_STATUS HsiOpenSlotControl( 
+	OUT HSI_SLOT_CONTROL_HANDLE *pHandle ); 
+
+HSI_STATUS HsiCloseSlotControl( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle ); 
+
+HSI_STATUS HsiGetSlotCount( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	OUT uint32 *pCount ); 
+
+HSI_STATUS HsiGetBoardPresent( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	IN uint32 Slot, 
+	OUT BOOLEAN *pPresent ); 
+
+HSI_STATUS HsiGetBoardHealthy( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	IN uint32 Slot, 
+	OUT BOOLEAN *pHealthy ); 
+
+HSI_STATUS HsiGetSlotPower( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	IN uint32 Slot, 
+	OUT BOOLEAN *pPower ); 
+
+HSI_STATUS HsiSetSlotPower( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	IN uint32 Slot, 
+	IN BOOLEAN Power ); 
+
+HSI_STATUS HsiGetSlotReset( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	IN uint32 Slot, 
+	OUT BOOLEAN *pReset ); 
+
+HSI_STATUS HsiSetSlotReset( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	IN uint32 Slot, 
+	IN BOOLEAN Reset ); 
+
+typedef struct HSI_SLOT_EVENT_INFO_STRUCT {
+	uint32 SlotNumber;
+	BOOLEAN Present;
+	BOOLEAN Powered;
+	BOOLEAN Healthy;
+	BOOLEAN InReset;
+} HSI_SLOT_EVENT_INFO;
+
+typedef void (*HSI_SLOT_EVENT_CALLBACK) (
+	IN void *pContext,
+	IN BOOLEAN HscError,
+	IN HSI_SLOT_EVENT_INFO *pSlotInfo );
+
+HSI_STATUS HsiSetSlotEventCallback( 
+	IN HSI_SLOT_CONTROL_HANDLE Handle, 
+	IN HSI_SLOT_EVENT_CALLBACK Callback, 
+	IN void *pContext );
+
+//
+// LINUX OS-dependent definitions
+//
+
+HSI_STATUS HsiPlatformGetFunctionTable ( 
+	OUT HSI_PLATFORM_FTABLE *pFtable );
+
+// Platform independent interface definitions
+typedef BOOLEAN (*QUERY_ENUM_ROUTINE)( 
+	void ); 
+
+typedef BOOLEAN (*IS_ENUM_INTERRUPT_ROUTINE)( 
+	IN void *pDeviceId ); 
+
+typedef HSI_STATUS (*ENABLE_ROUTINE)( 
+	void ); 
+
+typedef HSI_STATUS (*DISABLE_ROUTINE)( 
+	void ); 
+
+typedef void (*INTERRUPT_SERVICE_ROUTINE)( 
+	IN int Interrupt, 
+	IN void *pDeviceID, 
+	IN struct pt_regs *pRegisters );
+
+typedef struct HSI_INITIALIZATION_STRUCT { 
+	uint32 DevExtSize; 
+	int32 Intr; 
+	uint32 IntrFlags; 
+	void *pDevId; 
+	QUERY_ENUM_ROUTINE QueryEnumState; 
+	IS_ENUM_INTERRUPT_ROUTINE CheckEnumInterrupt; 
+	ENABLE_ROUTINE Enable; 
+	DISABLE_ROUTINE Disable; 
+	INTERRUPT_SERVICE_ROUTINE Isr; 
+	struct tq_struct Dpc; 
+} HSI_INIT; 
+
+HSI_STATUS HsiPlatformInitialize ( 
+	IN HSI_INIT *pInitData, 
+	OUT void **ppExt );
+
+HSI_STATUS HsiPlatformTerminate (
+	void );
+
+HSI_STATUS HsiPlatformGetInstanceData ( 
+	void **ppExt );
+
+HSI_STATUS HsiPlatformSignalEnum (
+	void );
+
+HSI_STATUS HsiPlatformGetEnumIrq ( 
+	IN uint32 IrqSet, 
+	OUT uint32 *pEnumIrq );
+
+// Platform dependent interface definitions
+BOOLEAN QueryEnumStateRoutine (
+	void );
+
+BOOLEAN CheckEnumInterruptRoutine (
+	IN void *pDeviceID );
+
+HSI_STATUS EnableRoutine (
+	void );
+
+HSI_STATUS DisableRoutine (
+	void );
+
+void IsrRoutine (
+	int Interrupt,
+	void *pDeviceID,
+	struct pt_regs *pRegisters );
+
+// 
+// Global variables
+//
+extern spinlock_t hsi_lock; 
+extern wait_queue_head_t hsi_platform_queue;
+extern BOOLEAN hsi_platform_initialized;
+
+extern int hsi_pid;
+extern int hsi_thread_registered;
+
+extern HSI_INIT hsi_platform_data;
+extern void *hsi_instance_data;
+extern void *hsi_enum_context;
+extern PLATFORM_ENUM_EVENT_CALLBACK hsi_EnumEventCallback;
+extern HSI_PLATFORM_FTABLE hsi_PlatformFtable;
+
+//
+// Constants
+//
+#define HSI_STATUS_SUCCESS		0
+#define HSI_STATUS_NO_MEMORY 		1
+#define HSI_STATUS_INVALID_PARAMETER 	2
+#define HSI_STATUS_NOT_IMPLEMENTED  	3
+#define HSI_STATUS_NO_SUCH_DEVICE   	4
+#define HSI_STATUS_NO_DATA_DETECTED 	5
+#define HSI_STATUS_OPERATION_NOT_APPLICABLE 6
+#define HSI_STATUS_NOT_AVAILABLE 7
+#define HSI_STATUS_FAILURE 		255
+
+#define HSI_MATCH_ANY_ID		0xA11C0DE  // Must be >65535
+#define HSI_FTABLE_VERSION 		0x0200 
+#define HSI_SLOT_CONFIG_VERSION 	0x0100 
+#define HSI_HSCSR_FTABLE_VERSION 	0x0200
+
+#endif
+
diff -u -r --new-file linux/drivers/ha/cpci/phs_zt5550.h ha/drivers/ha/cpci/phs_zt5550.h
--- linux/drivers/ha/cpci/phs_zt5550.h	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/phs_zt5550.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,86 @@
+/*
+ * phs_zt5550.h
+ *
+ * Ziatech 5550 platform-dependent include file for PICMG compatible 
+ * hot swap operations
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ * 2001Mar02 jfm - Original Version
+ */
+
+#ifndef LINUX_PICMG_HOTSWAP_ZT5550_H
+#define LINUX_PICMG_HOTSWAP_ZT5550_H
+
+#define ZIATECH_VENDOR_ID 0x1138
+#define ZT5550_HOSTCNTRL_DEVICE_ID 0x5550
+#define PCI_IOBASE_MASK ~0x3    /* mask for IO base address */
+#define PCI_MEMBASE_MASK ~0xf    /* mask for memory base address */
+
+#define ZT5550_EnumMask 0x40    /* Mask to get to the ENUM# bit on the bus */
+#define ZT5550_PortNum  0xe1    /* digital I/O port storing ENUM# */
+
+#define ZT5550_EnumEnableBit 0x04 /* Mask to get to ENUM# bit in HC register */
+
+/*
+ * defined handling that is unique to the version of LINUX
+ * that is used.
+ */
+
+#ifndef pci_resource_start
+#define pci_resource_start(dev, num) (dev->base_address[num])
+#endif
+
+#ifndef module_init
+#define module_init(x)  int init_module(void) { return x(); }
+#endif
+#ifndef module_exit
+#define module_exit(x)  void cleanup_module(void) { x(); }
+#endif
+ 
+typedef struct
+{
+	int16	bus;
+	uint8	device;
+	uint8	function; 
+} pciLocation;
+
+typedef struct
+{
+    uint32 baseAddrPtr;
+    uint16 intLevel;
+    pciLocation pci;
+ 
+    /* Host controller register addresses */
+    uint32 csr_hcindex;
+    uint32 csr_hcdata;
+    uint32 csr_intstat;
+    uint32 csr_intmask;
+} SATURN_PARAMS;
+
+#endif /* LINUX_PICMG_HOTSWAP_ZT5550_H */
+
diff -u -r --new-file linux/drivers/ha/cpci/piphs.c ha/drivers/ha/cpci/piphs.c
--- linux/drivers/ha/cpci/piphs.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/piphs.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,777 @@
+/*
+ * piphs.c
+ *
+ * Platform independent routines for PICMG 2.12 compatible hot swap.
+ *
+ * Author: MontaVista Software, Inc.
+ *	   source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ * 2001Mar13 jfm - Added Infrastructure requirements routines
+ * 2000Oct31 jfm - Original Version
+ *
+ */
+
+#include <linux/mm.h>
+#include <linux/interrupt.h>
+#include <linux/slab.h>
+#include <asm/irq.h>
+#include <linux/version.h>
+
+#include "phs.h"
+
+int HsiThreadRegister(void);
+int HsiThreadUnregister(void);
+
+//
+// Global variables
+//
+spinlock_t hsi_lock = SPIN_LOCK_UNLOCKED;  // hsi mutex
+BOOLEAN hsi_platform_initialized = FALSE;  // True when HsiPlatformInitialize
+					   //   has succeeded
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+wait_queue_head_t hsi_platform_queue;  	   //  platform thread waits here
+#else
+struct wait_queue *hsi_platform_queue;	   //  platform thread waits here
+#endif
+
+int hsi_pid = 0;		// PID for ENUM interrupt thread
+int hsi_thread_registered = 0;	// Number of registered users of platform thread
+ 
+HSI_INIT hsi_platform_data;	// contains copy of HSI_INIT struct
+void *hsi_instance_data;	// pointer to platform dependent data
+void *hsi_enum_context;		// value passed in to SetEnumEventCallback
+PLATFORM_ENUM_EVENT_CALLBACK hsi_EnumEventCallback; 
+				// Callback routine for ENUM events
+HSI_PLATFORM_FTABLE hsi_PlatformFtable;  // Function table for PI part
+
+
+/*
+ * Prototype: 
+ * void HsiPlatformEnumHandler( 
+ *	IN int Interrupt,
+ *	IN void *pDeviceId,
+ *	IN struct pt_regs *pRegisters ); 
+ *
+ * Arguments: 
+ * Interrupt - The interrupt number (e.g. IRQ) which caused the Interrupt 
+ *	Service Routine to be entered 
+ * pDeviceID - The unique device pointer used when the ISR was registered, 
+ *	i.e. the pDevID parameter from HsiPlatformInitialize() 
+ * pRegisters - A copy of the contents of the registers at the point of 
+ * interrupt 
+ *
+ * Return Value: 
+ * none 
+ *
+ * Synopsis:
+ * This is the default platform ENUM# interrupt handler. 
+ * It is called with interrupts off, and exits with interrupts still 
+ * off and the ENUM# interrupt disabled.  
+ *
+ * Note that the bottom half is run on the immediate queue - this is 
+ * for flexibility. If you want to wake up a thread, you will have to 
+ * write your bottom half appropriately.
+ *
+ * Algorithm:
+ * This function wakes up the ENUM interrupt handling thread.
+ * and marks a bottom half, if one has been identified.
+ * Note that this is called in interrupt mode (ints off).
+ *
+ */
+
+void HsiPlatformEnumHandler (
+	IN int Interrupt,
+	IN void *pDeviceId,
+	IN struct pt_regs *pRegisters ) 
+{
+	if (hsi_platform_data.CheckEnumInterrupt(pDeviceId)) {  // is it our int?
+		hsi_platform_data.Disable();		// yes, disable ENUM ints
+		wake_up_interruptible(&hsi_platform_queue); // and wake up the thread
+		if (hsi_platform_data.Dpc.routine != NULL) { // do we have a DPC?
+			queue_task(&hsi_platform_data.Dpc, &tq_immediate);  // queue it
+	    		mark_bh(IMMEDIATE_BH);		// mark it for execution
+		}
+	} else {
+		// spurious, or not our int, ignore
+	}
+}
+
+
+/*
+ * Prototype:
+ * BOOLEAN QueryEnumState(
+ *	 IN HSI_DEVICE *pDevice );
+ *
+ * Arguments: 
+ * pDevice   pointer to the specific instance of the platform device
+ *
+ * Return value:
+ * TRUE   if ENUM# is active
+ * FALSE  if ENUM# is inactive
+ *
+ * Synopsis:
+ * This function returns the current state of the ENUM# signal. 
+ * It may be called periodically by the Hot Swap System Driver to 
+ * retrieve the current ENUM# signal state.
+ *
+ * Algorithm:
+ * Returns the result of the platform-dependent QueryEnumState routine.
+ */
+
+BOOLEAN QueryEnumState(
+	IN HSI_DEVICE *pDevice )
+{
+	return hsi_platform_data.QueryEnumState();
+}
+
+
+/*
+ * Prototype:
+ * HSI_STATUS SetEnumEventCallback(
+ *	 IN HSI_DEVICE *pDevice,
+ *	 IN PLATFORM_ENUM_EVENT_CALLBACK Callback,
+ *	 IN void *pContext );
+ *
+ * Arguments:
+ * pDevice   pointer to the specific instance of the platform device.
+ * Callback  the address of the callback to call; NULL should be passed 
+ *	to cancel callback;
+ * pContext   an opaque pointer that will be passed unchanged to the
+ * callback routine.
+ *
+ * Return value:
+ * HSI_STATUS_SUCCESS   returned in the case of success
+ * Other HSI_STATUS values   if errors occurred during execution of this 
+ *	function
+ *
+ * Synopsis:
+ * This function is used by the client to specify the callback routine 
+ * that will be called when an ENUM# event occurs. The callback routine
+ * should have the following prototype:
+ *	 void Callback( IN void *pContext );
+ * The client should pass NULL to cancel the callback. This function 
+ * shall not be implemented by the Platform Driver if the platform does 
+ * not support ENUM# events.
+ *
+ */
+
+HSI_STATUS SetEnumEventCallback(
+	IN HSI_DEVICE *pDevice,
+	IN PLATFORM_ENUM_EVENT_CALLBACK Callback,
+	IN void *pContext )
+{
+printk("JSPJSP: SetEnumEventCallback %p\n", Callback);
+	hsi_enum_context = pContext;
+	hsi_EnumEventCallback = Callback;
+
+	if (hsi_platform_initialized) {
+		/* If initialized the wake the sleeping thread to
+		 * check for enums again.
+		 */
+		wake_up_interruptible(&hsi_platform_queue); 
+	}
+	return HSI_STATUS_SUCCESS;
+}
+
+
+/*
+ * Prototype:
+ * BOOLEAN EnableEnumEvents(
+ *	 IN HSI_DEVICE *pDevice,
+ *	 IN BOOLEAN State );
+ *
+ * Arguments:
+ * pDevice   pointer to the specific instance of the platform device
+ * State   TRUE to enable ENUM# events; FALSE to disable ENUM# events
+ *
+ * Return value: TRUE   If ENUM# events were enabled prior to the call
+ * FALSE   If ENUM# events were disabled prior to the call
+ *
+ * Synopsis:
+ * If the platform implements level-sensitive ENUM# interrupts, the
+ * interrupt request will be active as long as the ENUM# signal stays
+ * active. Since the ENUM# signal is not de-asserted by a device until
+ * both INS and EXT bits are cleared in its HS_CSR, it may stay active
+ * for a long time. To prevent infinite interrupt loops, ENUM# interrupts
+ * should be disabled using this function inside the event handler.
+ *
+ * This function should be used to re-enable ENUM# events after the client
+ * has processed all devices asserting ENUM# and has either cleared the
+ * INS and EXT bits, or masked the ENUM# assertion by setting the EIM bit
+ * in the HS_CSR.
+ *
+ * This function shall not be implemented by the Platform Driver if the
+ * platform does not support ENUM# events.
+ *
+ */
+
+BOOLEAN EnableEnumEvents(
+	IN HSI_DEVICE *pDevice,
+	IN BOOLEAN State )
+{
+	HSI_STATUS status;
+
+	if (State) {	// Enable ENUM events
+		status = hsi_platform_data.Enable();
+		if (status == HSI_STATUS_SUCCESS) {
+			return FALSE;	// ENUM events were disabled prior to call
+		}
+	} else {		// Disable ENUM events
+		status = hsi_platform_data.Disable();
+		if (status != HSI_STATUS_SUCCESS) {
+			return FALSE;	// ENUM events were disabled prior to call
+		}
+	}
+	return TRUE;	// ENUM events were enabled prior to call
+}
+
+
+/*
+ * Prototype: 
+ * HSI_STATUS HsiPlatformInitialize ( 
+ *	IN HSI_INIT *pInitData, 
+ *	OUT PVOID *ppExt ); 
+ *
+ * Arguments:
+ * pInitData - pointer to the initialization structure of type HSI_INIT
+ * ppExt - returns a pointer to a private data area for	use by the 
+ *	platform-dependent part of the driver. If pInitData->DevExtSize 
+ *	is 0, this pointer will be returned with a value of NULL.
+ *
+ * The HSI_INIT structure fields are defined as follows:
+ *
+ * DevExtSize - The number of bytes to allocate for private 
+ * 	platform-dependent data 
+ * Intr - The interrupt number (e.g. IRQ) of the ENUM# interrupt, 
+ * 	or -1 if ENUM# interrupts are not implemented by the platform 
+ * IntrFlags - Interrupt mode flags (SA_INTERRUPT, SA_SAMPLE_RANDOM, 
+ *	SA_SHIRQ, etc), or 0 
+ * pDevID - Unique pointer for the device. May be NULL if the ENUM# 
+ *	interrupt is not shared, if Isr is NULL, or if ENUM# interrupts 
+ *	are not implemented. This pointer is returned when the ISR is 
+ *	called 
+ * QueryEnumState - Address of the function in the platform-dependent 
+ * 	part that returns the current state of the ENUM# signal (mandatory) 
+ * CheckEnumInterrupt - Address of the function in the platform-dependent 
+ * 	part that can check if the current interrupt is an ENUM# interrupt, 
+ *	or NULL if ENUM# interrupts are not implemented by the platform 
+ * Enable - Address of the function in the platform-dependent part which 
+ *	enables ENUM# events, or NULL if ENUM# events are not implemented 
+ *	by the platform 
+ * Disable - Address of the function in the platform-dependent part which 
+ *	disables ENUM# events, or NULL if ENUM# events are not implemented 
+ *	by the platform 
+ * Isr - The ENUM# interrupt service routine address, or NULL to use the 
+ *	default platform-independent ISR 
+ * Dpc - The routine defined by Dpc will be added to the tq_immediate 
+ *	task queue for execution after any platform-independent bottom-half 
+ *	task. If the developer wishes to have this routine replace the 
+ *	platform-independent task, or have it attached to a different queue, 
+ *	they will have to implement their own isr routine.
+ *
+ * Return Value: 
+ * HSI_STATUS_SUCCESS   Platform initialization succeeded 
+ * HSI_STATUS_NO_MEMORY   The routine could not allocate the requested 
+ *	amount of memory for the private data area 
+ * HSI_STATUS_INVALID_PARAMETER   One of the parameters was invalid or 
+ *	out of range 
+ * HSI_STATUS_NOT_AVAILABLE   The interrupt number requested is already 
+ *	in use 
+ * Other HSI_STATUS values   Other errors occurred during execution of 
+ *	this function
+ *
+ * Synopsis: 
+ * This function initializes the platform-independent part of the 
+ * Platform Driver. It performs the following tasks: 
+ * - Fills in the function callback table for the 
+ *	HsiPlatformGetFunctionTable() function 
+ * - If the Interrupt number is not -1, attaches the appropriate 
+ *	ISR to the specified interrupt line
+ * - Allocates the requested private data block 
+ *
+ * Optional callbacks are included to do the following tasks for 
+ * platforms that implement ENUM# events; platforms that do not 
+ * implement ENUM# events should set these callbacks to NULL: 
+ *
+ * - Enable ENUM# events ; this function will be called indirectly 
+ * 	by the Hot Swap System Driver via the EnableEnumEvents function 
+ * 	after the current event has been processed. Only necessary on 
+ * 	platforms that have ENUM# events. 
+ * - Disable ENUM# events ; this function will be called from the 
+ *	event handler to disable further generation of ENUM# events. 
+ *	Only necessary on platforms that have ENUM# events. 
+ * - Check if the current interrupt was caused by ENUM#. Only necessary 
+ *	on platforms that have ENUM# interrupts. This function will only 
+ *	be called if the ENUM# interrupt line is shared (SA_SHIRQ flag 
+ * 	was set). 
+ *
+ * The other optional callbacks represent the interrupt service routine 
+ * and the function to call from the immediate bottom half handler that 
+ * is called after an ENUM# interrupt. It is recommended that you should 
+ * not specify these callbacks explicitly; default implementations 
+ * provided by the platform-independent part are sufficient for most cases. 
+ * The private memory allocated by this function is an area for storing 
+ * platform-dependent data. Its address is returned to the caller in the 
+ * output parameter ppExt.
+ *
+ */
+
+HSI_STATUS HsiPlatformInitialize ( 
+	IN HSI_INIT *pInitData,
+	OUT void **ppExt )
+{
+	int error;		// function return code
+	INTERRUPT_SERVICE_ROUTINE intr_routine;	// temp variable
+    
+	if (hsi_platform_initialized) {
+		return HSI_STATUS_OPERATION_NOT_APPLICABLE;
+	}
+
+	hsi_platform_data = *pInitData;	// save the struct for later use
+	if (pInitData->DevExtSize !=0) { // allocate the private data area
+		if ((hsi_instance_data = (void *)
+					kmalloc(hsi_platform_data.DevExtSize, 
+					GFP_KERNEL)) == NULL) {
+			return HSI_STATUS_NO_MEMORY; // kmalloc failed!
+		}
+	} else {  				// no private data area requested
+		hsi_instance_data = NULL;		// spec says to null the pointer
+	}
+
+	*ppExt = hsi_instance_data;
+
+	if (pInitData->Intr > 0) {
+		if (pInitData->Isr) {		// assign ENUM# handler
+			intr_routine = pInitData->Isr;
+		} else {
+			intr_routine = HsiPlatformEnumHandler;
+			HsiThreadRegister();
+		}
+
+		// Get the requested IRQ
+		error = request_irq((uint32)pInitData->Intr, intr_routine,
+				pInitData->IntrFlags, "hotswap",
+				pInitData->pDevId);
+		if (error < 0) {
+			if ((error = -EINVAL)) return HSI_STATUS_INVALID_PARAMETER;
+			if ((error = -ENOMEM)) return HSI_STATUS_NO_MEMORY;
+			if ((error = -EBUSY)) return HSI_STATUS_NOT_AVAILABLE;
+			return HSI_STATUS_FAILURE;
+		}
+	}
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,4,0)
+	init_waitqueue_head(&hsi_platform_queue);
+#endif
+
+	hsi_PlatformFtable.Version = HSI_FTABLE_VERSION;
+	hsi_PlatformFtable.Size = sizeof(HSI_PLATFORM_FTABLE);
+	hsi_PlatformFtable.QueryEnumStateFunc = QueryEnumState;
+	hsi_PlatformFtable.SetEnumEventCallbackFunc = SetEnumEventCallback;
+	hsi_PlatformFtable.EnableEnumEventsFunc = EnableEnumEvents;
+
+
+	// perform any other initialization here
+
+	hsi_platform_initialized = TRUE;
+
+	return HSI_STATUS_SUCCESS;		// all done!
+}
+
+
+/*
+ * Prototype:
+ * HSI_STATUS HsiPlatformGetFunctionTable (
+ *	 OUT HSI_PLATFORM_FTABLE *pFtable )
+ *
+ * Arguments:
+ * pFtable   Pointer to the HSI_PLATFORM_FTABLE struct that will hold the
+ *	function table implemented by the Platform Driver
+ *
+ * Return Value: 
+ * HSI_STATUS_SUCCESS   This function always succeeds
+ *
+ * Synopsis:
+ * This function obtains the set of functions implemented by the Platform
+ * Driver for use by the kernel space client (Hot Swap System Driver).
+ *
+ */
+
+HSI_STATUS HsiPlatformGetFunctionTable (
+	OUT HSI_PLATFORM_FTABLE *pFtable )
+{
+	*pFtable = hsi_PlatformFtable;
+	return HSI_STATUS_SUCCESS;
+}
+
+
+/*
+ * Prototype: 
+ * HSI_STATUS HsiPlatformTerminate( 
+ *	void ); 
+ *
+ * Arguments: 
+ * none 
+ *
+ * Return Value: 
+ * HSI_STATUS_SUCCESS - This function always succeeds 
+ *
+ * Synopsis: 
+ * This function prepares the platform-independent part of the 
+ * Platform Driver for graceful termination. It should be called from the 
+ * cleanup_module() routine of the platform-dependent part. The 
+ * HsiPlatformTerminate() routine will free any allocated IRQ (if not 
+ * currently shared), free the platform-dependent data area (if any), 
+ * and release all other resources allocated by the HsiPlatformInitialize() 
+ * function.
+ *
+ */
+
+HSI_STATUS HsiPlatformTerminate (
+	void )
+{
+	if (hsi_platform_data.Intr > 0) {
+		free_irq(hsi_platform_data.Intr, hsi_platform_data.pDevId);
+		if (hsi_platform_data.Isr == NULL) {
+			HsiThreadUnregister();	// Unregister the default handler
+		}
+	}
+
+	if (hsi_instance_data) { 		// private data area allocated?
+		kfree(hsi_instance_data);	//   yes, free it
+		hsi_instance_data = NULL;
+	}
+
+	hsi_platform_initialized = FALSE;
+
+	return HSI_STATUS_SUCCESS;		// All done!
+}
+
+
+/*
+ * Prototype: 
+ * HSI_STATUS HsiPlatformGetInstanceData ( 
+ * 	void **ppExt );
+ *
+ * Arguments: 
+ * ppExt - Pointer to the private block of memory for use by the 
+ * 	platform-dependent part of the driver. If none was allocated, 
+ *	this pointer will be null 
+ *
+ * Return Value: 
+ * HSI_STATUS_SUCCESS - The function succeeded 
+ * HSI_STATUS_NOT_AVAILABLE - The platform is not currently initialized 
+ * Other HSI_STATUS values - Other errors occurred during execution of 
+ *	this function 
+ *
+ * Synopsis: 
+ * This function makes it possible for the platform-dependent part to get
+ * access to the private data area allocated by the HsiPlatformInitialize() 
+ * function. The size of this area is specified by the DevExtSize parameter 
+ * when calling HsiPlatformInitialize().
+ *
+ */
+
+HSI_STATUS HsiPlatformGetInstanceData (
+	void **ppExt )
+{
+	if (!hsi_platform_initialized) {	// oops!
+		return HSI_STATUS_NOT_AVAILABLE;
+	}
+
+	*ppExt = hsi_instance_data;
+	return HSI_STATUS_SUCCESS;
+}
+
+
+/* 
+ * Prototype: 
+ * HSI_STATUS HsiPlatformSignalEnum ( 
+ *	void ); 
+ *
+ * Arguments: 
+ * none 
+ *
+ * Return Value: 
+ * HSI_STATUS_SUCCESS - This function always succeeds 
+ *
+ * Synopsis: 
+ * This function is called by the platform-dependent part to notify 
+ * the platform-independent part that an ENUM# event has occurred. 
+ * In response, the platform-independent part propagates this notification 
+ * to the clients of the platform driver. The platform-dependent part will 
+ * call this function if it performs ENUM# detection in a non-standard way 
+ * (other than by an edge-triggered or level-sensitive interrupt). 
+ * One possible scenario where this function might be useful is the 
+ * ACPI-based ENUM# detection, where the ENUM# signal is mapped onto an 
+ * ACPI event. An alternative scenario is that the platform-dependent part 
+ * performs its own handling of ENUM# interrupts, but still needs to notify 
+ * the client about the ENUM# event.
+ *
+ */
+
+HSI_STATUS HsiPlatformSignalEnum (
+	void )
+{
+	if (hsi_EnumEventCallback != NULL) {
+		/* Call the callback */
+		hsi_EnumEventCallback(hsi_enum_context);
+	} else {
+		/* If there is not function to process the enum then
+		 * sleep waiting until it is set.
+		 */
+		interruptible_sleep_on(&hsi_platform_queue);
+	}
+	return HSI_STATUS_SUCCESS;
+}
+
+
+/*
+ * Prototype: 
+ * HSI_STATUS HsiPlatformGetEnumIrq ( 
+ *	IN ULONG IrqSet, 
+ *	OUT ULONG *pEnumIrq );
+ *
+ * Arguments: 
+ * IrqSet - A set of bits corresponding to IRQ values to try. A 1 means 
+ *	try the IRQ value corresponding to that bit position, a 0 means 
+ *	don't try that IRQ 
+ * pEnumIrq - An output parameter which receives the IRQ value assigned 
+ * 	by the system 
+ *
+ * Return Value: 
+ * HSI_STATUS_SUCCESS - An available IRQ was found 
+ * HSI_STATUS_NOT_AVAILABLE - no unused IRQs were available in the set 
+ * 	specified 
+ * HSI_STATUS_INVALID_PARAMETER - Bits were set in IrqSet which don't 
+ * 	correspond to a valid IRQ 
+ * Other HSI_STATUS values - Other errors occurred during execution of 
+ * 	this function 
+ *
+ * Synopsis: 
+ * This function can be called by the platform-dependent part if the 
+ * platform has a choice of several IRQs to be used for the ENUM# signal. 
+ * In that case, this function will select an available IRQ from the pool 
+ * of unused IRQs. The platform-dependent part obtains the IRQ prior to 
+ * calling the HsiPlatformInitialize() function. If the platform-dependent 
+ * part uses a fixed IRQ, it need not call HsiPlatformGetEnumIrq(), but 
+ * may directly pass this fixed value to the HsiPlatformInitialize() 
+ * function. Note that this function does not allocate or reserve the IRQ, 
+ * that must be done by the HsiPlatformInitialize() function. 
+ * HsiPlatformTerminate() is responsible for de-allocating and returning 
+ * all resources claimed by HsiPlatformInitialize()
+ * 
+ * Algorithm: 
+ * Try all IRQs in the set to find the first which has no action list,
+ * and thus is free.  Note that this is architecture dependent, and 
+ * probably OS revision dependent as well.  An alternative method would
+ * be to use probe_irq_on and use the set returned, but that is a lot
+ * more overhead.  Another alternative would be to try all irqs in the
+ * set with request_irq, but that is pretty wasteful as well.
+ *
+ * Note that this is not done with ints off, and so might return a
+ * result which is in fact no longer available.  This possibility should
+ * be dealt with by the code in HsiPlatformInitialize(). This code does
+ * not deal with the possibility of shared interrupts, but could be
+ * extended to do so.  That is left as an exercise to the interested
+ * reader.
+ */
+
+HSI_STATUS HsiPlatformGetEnumIrq (
+	IN uint32 IrqSet,
+	OUT uint32 *pEnumIrq )
+{
+#if !defined(CONFIG_PPC)
+	uint32 try_irq;
+	
+	for (try_irq=1; try_irq < 32; try_irq++) {
+		if ((1<<try_irq) & IrqSet) {
+			if (irq_desc[try_irq].action == NULL) { 
+				*pEnumIrq = try_irq;
+				return HSI_STATUS_SUCCESS;
+			}
+		}
+	}
+#endif /* CONFIG_PPC */
+	return HSI_STATUS_NOT_AVAILABLE;
+}
+
+ 
+/* 
+ * Prototype: 
+ * int HsiPlatformThread ( 
+ *	void * pParms); 
+ *
+ * Arguments: 
+ * pParms	Pointer to generic parameter (not used) 
+ *
+ * Return Value: 
+ * -1	This function only returns if interrupted by a signal. 
+ *
+ * Synopsis: 
+ * This is a thread which handles the ENUM# requests.  It is intended
+ * to be able to handle other HSI requests, but they should be added 
+ * carefully.  Specifically, it is important to not lose any interrupts 
+ * which may come in during processing of other tasks.  This means that
+ * the main loop and sleep condition need to be reworked if other 
+ * interrupts or HSI requests are to be added.
+ *
+ * Algorithm:
+ * release unused resources when started, then sleep on the
+ * hsi_platform_queue wait queue until woken up.  Currently,
+ * the only waking conditions are signals and the ENUM interrupt.
+ *
+ * Any signal except SIGUSR1 will terminate the thread.
+ *
+ */
+int HsiPlatformThread (
+	void * pParms )
+{
+	uint32 sig_num;
+	siginfo_t sig_info;
+	unsigned long flags;
+	exit_mm(current);	// release some unneeded resources
+	exit_files(current);
+	exit_fs(current);
+
+	strcpy(current->comm, "tHsi");	// give the thread a name
+
+	while (TRUE) {
+		spin_lock_irqsave(&hsi_lock, flags);
+		if (!hsi_platform_data.QueryEnumState()) {
+			hsi_platform_data.Enable();	// re-enable ENUM interrupts
+			interruptible_sleep_on(&hsi_platform_queue);
+		}
+		spin_unlock_irqrestore(&hsi_lock, flags);
+ 
+		// If we were woken up by a signal, see if it's useful, otherwise exit.
+		if (signal_pending(current)) {
+			/* sending SIGUSR1 makes us print out some info */
+			spin_lock_irq(&current->sigmask_lock);
+			sig_num = dequeue_signal(&current->blocked, &sig_info);
+			spin_unlock_irq(&current->sigmask_lock);
+ 
+			if(sig_num == SIGUSR1) {
+				printk(KERN_DEBUG "tHsiEnum: could dump some useful info here\n");
+			} else {
+				/* unknown signal, exit the thread */
+				break;
+			}
+		}
+		// check if ENUM signal is asserted
+		while (hsi_platform_data.QueryEnumState()) {
+			HsiPlatformSignalEnum();
+		}
+	}	// while TRUE
+	return -1;
+}
+
+
+/* 
+ * Prototype: 
+ * int HsiThreadRegister ( 
+ *	void ); 
+ *
+ * Arguments: 
+ * none 
+ *
+ * Return Value: 
+ * none 
+ *
+ * Synopsis: 
+ * This routine starts the Hsi platform thread. Currently, the
+ * Hsi Platform thread only does ENUM interrupts, but if other
+ * services use the thread, they should register here as well.
+ * Only the first call actually creates the thread.
+ *
+ * Algorithm:
+ * Check to see if thread already created.  If the thread is not
+ * already created, create the thread.  In either case, increment the 
+ * hsi_thread_registered counter
+ *
+ */
+
+int HsiThreadRegister(
+	void )
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsi_lock, flags);
+	if (hsi_pid<=0) {
+		spin_unlock_irqrestore(&hsi_lock, flags);
+		hsi_pid = kernel_thread(HsiPlatformThread, NULL,
+				CLONE_FS | CLONE_FILES | CLONE_SIGHAND);
+		spin_lock_irqsave(&hsi_lock, flags);
+	}
+	if (hsi_pid>0) {
+		hsi_thread_registered++;
+	}
+	spin_unlock_irqrestore(&hsi_lock, flags);
+	return hsi_pid;
+}
+
+
+/* 
+ * Prototype: 
+ * void HsiThreadUnregister ( 
+ *	void); 
+ *
+ * Arguments: 
+ * none 
+ *
+ * Return Value: 
+ * none 
+ *
+ * Synopsis: 
+ * This routine stops the Hsi platform thread. Currently, the
+ * Hsi Platform thread only does ENUM interrupts, but if other
+ * services use the thread, they should unregister here as well.
+ * The thread will only be killed when the last user unregisters.
+ *
+ * Algorithm:
+ * Decrement the hsi_thread_registered counter.  If it is now 0,
+ * kill the Hsi Platform Thread.
+ *
+ */
+
+int HsiThreadUnregister (
+	void )
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&hsi_lock, flags);
+/* how paranoid should we be?  check for 0 first?   */
+	if (!--hsi_thread_registered) {
+		/*  This may be a long time to hold a spin lock, but
+		 * you don't want the thread to try to restart while you
+		 * are killing it.
+		 */
+		kill_proc_info(SIGSTOP, (void *)1L, hsi_pid);
+	}
+	spin_unlock_irqrestore(&hsi_lock, flags);
+
+	return HSI_STATUS_SUCCESS;
+}
diff -u -r --new-file linux/drivers/ha/cpci/zia5083cpci.c ha/drivers/ha/cpci/zia5083cpci.c
--- linux/drivers/ha/cpci/zia5083cpci.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/cpci/zia5083cpci.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,475 @@
+/*
+ * zia5083cpci.c
+ *
+ * Ziatech zt5083 specific cPCI control routines.
+ *
+ * Author: MontaVista Software, Inc.
+ *         tsa@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ * 
+ * Revision History (most recent first)
+ *
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_auto.h>
+#include <linux/cpci.h>
+#include <asm/pci.h>
+#include <asm/delay.h>
+#include "cpci_core.h"
+
+int  zia5083cpci_early_config_bus(struct pci_controller *, int, int);
+void zia5083cpci_find_driver(int);
+struct pci_ops *pci_check_direct(void);
+struct pci_ops *pci_find_bios(void);
+
+int  ZT5550_init(void);
+
+extern struct pci_ops *pci_root_ops;
+
+#define ZIAHSC_BUS1_DEVFN PCI_DEVFN(0x08, 0)
+#define ZIAHSC_BUS2_DEVFN PCI_DEVFN(0x0c, 0)
+#define HSC_DEVFN PCI_DEVFN(0xb, 0)
+#define AGP_DEVFN PCI_DEVFN(0x1, 0)
+#define PIXX4_HB_DEVFN PCI_DEVFN(0x7, 0)
+
+#define ZIA_NUM_SLOTS 16
+
+unsigned int ZiaIoSize[] = {
+	CONFIG_ZIA_5083_SLOT1_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT2_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT3_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT4_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT5_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT6_IO_SIZE,
+	0, 0, 0, 0,
+	CONFIG_ZIA_5083_SLOT11_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT12_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT13_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT14_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT15_IO_SIZE,
+	CONFIG_ZIA_5083_SLOT16_IO_SIZE,
+};
+
+unsigned int ZiaMemSize[] = {
+	CONFIG_ZIA_5083_SLOT1_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT2_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT3_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT4_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT5_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT6_MEM_SIZE,
+	0, 0, 0, 0,
+	CONFIG_ZIA_5083_SLOT11_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT12_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT13_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT14_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT15_MEM_SIZE,
+	CONFIG_ZIA_5083_SLOT16_MEM_SIZE,
+};
+
+CpciNodeInfo ZiaBusInfo[] = {
+	{NULL, 0x0, 0x0, 0, 0, 0x07, 0x37, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0, 0x0, 0, 0, 0x47, 0x77, 0x0, 0x0, 0x0, 0x0}
+};
+
+CpciNodeInfo ZiaSlotInfo[] = {
+	{NULL, 0X7,  PCI_DEVFN(0xa,0), 0, 0, 0x08, 0x0f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xb,0), 0, 0, 0x10, 0x17, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xc,0), 0, 0, 0x18, 0x1f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xd,0), 0, 0, 0x20, 0x27, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xe,0), 0, 0, 0x28, 0x2f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x7,  PCI_DEVFN(0xf,0), 0, 0, 0x30, 0x37, 0x0, 0x0, 0x0, 0x0},
+
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x0,  0x0,              0, 0, 0x0,  0x0,  0x0, 0x0, 0x0, 0x0},
+
+	{NULL, 0x47, PCI_DEVFN(0xf,0), 0, 0, 0x48, 0x4f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xe,0), 0, 0, 0x50, 0x57, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xd,0), 0, 0, 0x58, 0x5f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xc,0), 0, 0, 0x60, 0x67, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xb,0), 0, 0, 0x68, 0x6f, 0x0, 0x0, 0x0, 0x0},
+	{NULL, 0x47, PCI_DEVFN(0xa,0), 0, 0, 0x70, 0x77, 0x0, 0x0, 0x0, 0x0}
+};
+
+CpciInfo ZiaCpciInfo = {CPCI_CHASSIS_ZIA_5083,	/* Chassis type */
+			2,	  /*  Number of buses. */
+			{0, 10},  /* Bus start slot numbers. */
+			{5, 15}   /* Bus end slot numbers. */
+		       };
+
+static struct pci_controller* MainHose;
+
+unsigned char zia5083CpciIrqs[2][4];
+
+#define PCI_LOWER_IO  0x1000
+#define PCI_UPPER_IO  0xf000
+#define PCI_LOWER_MEM 0x50000000
+#define PCI_UPPER_MEM 0xf4000000
+#define ISA_IO_BASE   0x0
+#define ISA_MEM_BASE  0x0
+
+#define PCI_IO_CPCI_START 0x010000
+#define PCI_MEM_CPCI_START 0xe8000000
+
+int
+zia5083cpci_ignore_agp(struct pci_controller *hose, int bus, int devfn)
+{
+	return 0;
+}
+
+struct pci_auto_addrs PciAddrs = {
+	PCI_LOWER_IO, PCI_UPPER_IO, PCI_LOWER_MEM, PCI_UPPER_MEM
+};
+
+/*
+ * Provide the find bridges functionality needed from the architecture
+ * specific boot code.  Instead of the old method of using the firmware
+ * set value, do pci autoscan and with exceptions for the cPCI bridge chips.
+ */
+void __init
+zia5083cpci_find_bridges(void)
+{
+	int loop;
+	unsigned char Pirq;
+	int LastIo;
+	int LastMem;
+
+	printk("Initialize the PCI bridge tree for the Ziatech ZT5083 cPCI chassis\n");
+
+	MainHose = pciauto_alloc_controller();
+
+	if (!MainHose)
+		return;
+
+	MainHose->first_busno = 0;
+	MainHose->last_busno = 0xff;
+	MainHose->pci_mem_offset = ISA_MEM_BASE;
+	MainHose->mem_space.start = PciAddrs.mem_start;
+	MainHose->mem_space.end = PciAddrs.mem_end;
+	MainHose->io_base_virt = (void *)ISA_IO_BASE;
+	MainHose->io_space.start = PciAddrs.io_start;
+	MainHose->io_space.end = PciAddrs.io_end;
+	MainHose->mem_resources[0].end = 0xffffffff;
+
+	MainHose->ops = pci_root_ops;
+	MainHose->cfg_addr = (unsigned int *)NULL;  /* Not used on intel arch */
+	MainHose->cfg_data = (unsigned char *)NULL;
+
+	/* Need to get the PIRQ values and set eny not initilaized */
+	for (loop = 0; loop < 4; loop++) {
+		early_read_config_byte(MainHose, 0, PIXX4_HB_DEVFN,
+				       0x60 + loop, &Pirq);
+
+		if (Pirq == 0x80) {
+			Pirq = 5;
+			early_write_config_byte(MainHose, 0, PIXX4_HB_DEVFN,
+						0x60 + loop, Pirq);
+		}
+
+		zia5083CpciIrqs[0][loop] = Pirq;
+		zia5083CpciIrqs[1][loop] = Pirq;
+	}
+
+
+	ZiaBusInfo[0].DevFn = ZIAHSC_BUS1_DEVFN;	/* Bus A */
+	ZiaBusInfo[1].DevFn = ZIAHSC_BUS2_DEVFN;	/* Bus B */
+
+	/* Tell the cPCI core routines where the slot table exists. */
+	CpciBuses = ZiaBusInfo;
+	CpciSlots = ZiaSlotInfo;
+	CpciInfos = &ZiaCpciInfo;
+
+	/* Do not scan the cPCI bus bridges.  Let the hot insert do that later */
+	pci_excpt_setup_bridge_bdev(MainHose, 0, ZIAHSC_BUS1_DEVFN,
+						zia5083cpci_early_config_bus);
+	pci_excpt_setup_bridge_bdev(MainHose, 0, ZIAHSC_BUS2_DEVFN,
+						zia5083cpci_early_config_bus);
+	pci_excpt_setup_bridge_bdev(MainHose, 0, AGP_DEVFN,
+						zia5083cpci_ignore_agp);
+
+	LastIo = PCI_IO_CPCI_START;
+	LastMem = PCI_MEM_CPCI_START;
+
+	for (loop = ZIA_NUM_SLOTS - 1; loop > -1; loop--) {
+		ZiaSlotInfo[loop].IoEnd = LastIo;
+		LastIo -= ZiaIoSize[loop] * 1024;
+
+		if (LastIo < PciAddrs.io_start) {
+			panic("PCI system has too much IO space allocated\n");
+		}
+
+		ZiaSlotInfo[loop].IoStart = LastIo;
+
+		ZiaSlotInfo[loop].MemEnd = LastMem;
+		LastMem -= ZiaMemSize[loop] * 1024 * 1024;
+
+		if (LastMem < PciAddrs.mem_start) {
+			panic("PCI system has too much Memory space allocated\n");
+		}
+
+		ZiaSlotInfo[loop].MemStart = LastMem;
+	}
+
+	/* Set the bus start and end address based on the correct slot addresses */
+	ZiaBusInfo[0].IoStart = ZiaSlotInfo[0].IoStart;
+	ZiaBusInfo[0].IoEnd = ZiaSlotInfo[5].IoEnd;
+	ZiaBusInfo[0].MemStart = ZiaSlotInfo[0].MemStart;
+	ZiaBusInfo[0].MemEnd = ZiaSlotInfo[5].MemEnd;
+
+	ZiaBusInfo[1].IoStart = ZiaSlotInfo[10].IoStart;
+	ZiaBusInfo[1].IoEnd = ZiaSlotInfo[15].IoEnd;
+	ZiaBusInfo[1].MemStart = ZiaSlotInfo[10].MemStart;
+	ZiaBusInfo[1].MemEnd = ZiaSlotInfo[15].MemEnd;
+
+	if ((pciauto_bus_scan(MainHose, MainHose->first_busno,
+			      &PciAddrs)) == -1) {
+		panic("PCI system needs more than the available PCI address space\n");
+	}
+
+	MainHose->last_busno = ZiaBusInfo[1].LastBusNo;
+
+	/* Set the host bridge to properly cover the whole pci address space. */
+	PciAddrs.io_end = ZiaBusInfo[0].IoStart;
+	PciAddrs.mem_end = ZiaBusInfo[0].MemStart;
+	pciauto_postscan_setup_bridge(MainHose, 0, 0, ZiaBusInfo[1].LastBusNo, &PciAddrs);
+
+	/* Recode the Hose info for each slot for later use. */
+	ZiaBusInfo[0].Hose = MainHose;
+	ZiaBusInfo[1].Hose = MainHose;
+
+	for (loop = 0; loop < ZIA_NUM_SLOTS; loop++) {
+		ZiaSlotInfo[loop].Hose = MainHose;
+	}
+}
+
+/*
+ * This function is called from the pci autoscan routine when the cPCI
+ * bridges are found.
+ */
+int
+zia5083cpci_early_config_bus(struct pci_controller *hose, int bus, int devfn)
+{
+	int ZiaBus;
+	int Slot;
+	int RetVal;
+	unsigned short Command;
+
+	if (devfn == CpciBuses[0].DevFn) {
+		ZiaBus = 0;
+	} else {
+		ZiaBus = 1;
+	}
+
+	CpciConfigCpciBridge(hose, bus, devfn, ZiaBus);
+	CpciBuses[ZiaBus].Allocated = 1;
+
+	for (Slot = CpciInfos->StartSlotNum[ZiaBus];
+			Slot <= CpciInfos->EndSlotNum[ZiaBus]; Slot++) {
+		if ((RetVal = CpciConfigSlot(Slot, MainHose, CpciBuses[ZiaBus].FirstBusNo)) < 0) {
+			if (RetVal == -ENOENT) {
+				/* Nothing in the slot. */
+				continue;
+			}
+
+			/* config problems on this slot so disable access */
+			early_read_config_word(hose,
+					       CpciBuses[ZiaBus].FirstBusNo,
+					       CpciSlots[Slot].DevFn,
+					       PCI_COMMAND, &Command);
+			Command &= ~(PCI_COMMAND_IO | PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+			early_write_config_word(hose,
+						CpciBuses[ZiaBus].FirstBusNo,
+					        CpciSlots[Slot].DevFn,
+					        PCI_COMMAND, Command);
+			CpciSlots[Slot].Allocated = CPCI_SLOT_INSFAILED;
+		}
+	}
+
+	return 0;
+}
+
+void
+zia5083routeNon0Irq(struct pci_dev *dev)
+{
+	struct pci_bus *TempBus = dev->bus;
+	unsigned int DevNum = PCI_SLOT(dev->devfn);
+
+	while (TempBus->parent->primary != TempBus->parent->secondary) {
+		DevNum += PCI_SLOT((TempBus->self)->devfn);
+		TempBus = TempBus->parent;
+	}
+
+	DevNum &= 0x03;
+
+	if (dev->bus->number > CpciBuses[0].LastBusNo) {
+		if (ZiaBusInfo[0].DevFn == ZIAHSC_BUS1_DEVFN) {
+			dev->irq = zia5083CpciIrqs[1][DevNum];
+		} else {
+			dev->irq = zia5083CpciIrqs[0][DevNum];
+		}
+	} else {
+		if (ZiaBusInfo[0].DevFn == ZIAHSC_BUS1_DEVFN) {
+			dev->irq = zia5083CpciIrqs[0][DevNum];
+		} else {
+			dev->irq = zia5083CpciIrqs[1][DevNum];
+		}
+	}
+
+	pci_write_config_byte(dev, PCI_INTERRUPT_LINE, (unsigned char)dev->irq);
+}
+
+/* Prototypes Zia specific functions needed externally */
+//int	zia5083hscAllocateAndInitBus(int);
+//void	zia5083hscDeallocateAndShutdownBus(int);
+//int	zia5083hscSetEnumMask(int, int);
+//int	zia5083hscCheckHealthy(int);
+
+static int
+ReturnTrue1(int arg)
+{
+		return 1;
+}
+
+static int
+ReturnTrue2(int arg1, int arg2)
+{
+		return 1;
+}
+
+static int
+ReturnFalse(int arg)
+{
+		return 0;
+}
+
+void	Powerplus_Map_Non0(struct pci_dev *);
+
+/* This data structure contains the hardware dependent functions to
+ * provide functionality for independent code segments.
+ * */
+CpciFunc ZiaCpciFuncs = {
+		/*
+	zia5083hscAllocateAndInitBus,
+	zia5083hscDeallocateAndShutdownBus,
+	zia5083hscSetEnumMask,
+	zia5083hscCheckHealthy,
+	*/
+	ReturnTrue1,
+	ReturnTrue1,
+	ReturnTrue2,
+	ReturnTrue1,
+	zia5083routeNon0Irq
+};
+
+extern struct list_head pci_root_buses;
+extern struct pci_controller* hose_head;
+
+void
+zia5083cpci_init(void)
+{
+	struct pci_bus *HeadBus;
+//	int StatusBusA = 0, StatusBusB = 0;
+//	int delay_count;
+
+	/* Initialize enum control. */
+	ZT5550_init();
+
+	/* Export dependent function structure. */
+	CpciFunctions = &ZiaCpciFuncs;
+
+	/* Reset the hose and top level bus info to reality for HA numbers */
+	hose_head->last_busno = CpciBuses[1].LastBusNo;
+
+	HeadBus = pci_bus_b(pci_root_buses.next);
+	HeadBus->subordinate = CpciBuses[1].LastBusNo;
+
+	/* For each bus, power on and connect each slot to the bus.  At this
+	 * time check to see if healthy has been set on the slot and 
+	 * set up the pci tree if it has.
+	 */
+
+//	StatusBusA = zia5083hscAllocateAndInitBus(ZIAHSC_BUSA);
+//	StatusBusB = zia5083hscAllocateAndInitBus(ZIAHSC_BUSB);
+//
+//	for (delay_count = 0; delay_count < 500; delay_count++) {
+//		udelay(10);
+//	}
+//
+//	if (zia5083hscBusStatus(ZIAHSC_BUSA)) {
+//		if (StatusBusA) {
+//			/* This bus was just added */
+//			CpciSetupBus(ZIAHSC_BUSA);
+//		} else {
+//			/* Bus was powered on at boot.  Need to allert 
+//			 * system to download driver if needed. */
+//			zia5083cpci_find_driver(ZIAHSC_BUSA);
+//		}
+//	}
+//
+//	if (zia5083hscBusStatus(ZIAHSC_BUSB)) {
+//		if (StatusBusB) {
+//			/* This bus was just added */
+//			CpciSetupBus(ZIAHSC_BUSB);
+//		} else {
+//			/* Bus was powered on at boot.  Need to allert 
+//			 * system to download driver if needed. */
+//			zia5083cpci_find_driver(ZIAHSC_BUSB);
+//		}
+//	}
+}
+
+void
+zia5083cpci_find_driver(int bus)
+{
+	struct pci_dev *Dev;
+	int Slot, LastSlot = -1, SlotSubDev = 0;
+
+	pci_for_each_dev(Dev) {
+		if ((Dev->bus->number >= CpciBuses[bus].FirstBusNo) &&
+		    (Dev->bus->number <= CpciBuses[bus].LastBusNo)) {
+
+			if ((Slot = CpciFindSlotFromDev(Dev)) < 0) {
+				continue;
+			}
+
+			if ((Dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
+				continue;
+			}
+
+			if (Slot != LastSlot) {
+				LastSlot = Slot;
+		    		SlotSubDev = 0;
+			}
+
+			CpciFunctions->MapIrq(Dev);
+			Dev->cpci_location = (Slot << 16) | SlotSubDev++;
+
+			CpciRegisterOpenCheck(Dev);
+		}
+	}
+}
diff -u -r --new-file linux/drivers/ha/event/Makefile ha/drivers/ha/event/Makefile
--- linux/drivers/ha/event/Makefile	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/event/Makefile	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,15 @@
+#
+# Makefile for the Eventing Mechanism implementation.
+#
+
+O_TARGET	:= event.o
+
+obj-y   := event_core.o user_api.o kernel_api.o debug.o
+obj-m   :=
+obj-n   :=
+obj-    :=
+
+export-objs := event_core.o kernel_api.o
+
+include $(TOPDIR)/Rules.make
+
diff -u -r --new-file linux/drivers/ha/event/debug.c ha/drivers/ha/event/debug.c
--- linux/drivers/ha/event/debug.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/event/debug.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,97 @@
+/*
+ * debug.c
+ *
+ * Routines used to debug various problems with the eventing mechanism.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/event.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "event_core.h"
+
+void
+DumpClassList(void)
+{
+	int Hash;
+	KernelClassInfo *HashBase;
+	EventDestBase *EventBase;
+	EventDest *Dest;
+
+	printk("  Dump Class List:\n");
+	for (Hash = 0; Hash < NUM_EVENT_HASHES; Hash++) {
+		HashBase = &KernelClassHash[Hash];
+
+		while (HashBase->Next) {
+			printk("    0x%x Hash %d Class %d Name \"%s\"\n", HashBase, Hash,
+				HashBase->Class, HashBase->ClassString);
+
+			EventBase = HashBase->EventQ;
+			while (EventBase->Next != NULL) {
+				printk("        Event %d count %d\n", EventBase->Event, EventBase->UseCount);
+
+				Dest = &EventBase->DestQ;
+				while (Dest->Next != NULL) {
+				printk("            User Id %d Priority %d Callback %p UserInfo %p KernelInfo %p\n",
+				       Dest->Id, Dest->Pri, Dest->KernelCB,
+				       Dest->UserInfo, Dest->KernelInfo);
+					Dest = Dest->Next;
+				}
+
+				EventBase = EventBase->Next;
+			}
+
+			HashBase = HashBase->Next;
+		}
+	}
+
+	return;
+}
+
+void
+DumpUsersList(void)
+{
+	KernelUserInfo *TmpUser = KernelUsersHead;
+
+	while (TmpUser) {
+		printk("Dumping users list\n");
+		printk("    User %d is \"%s\"\n", TmpUser->Id, TmpUser->IdString);
+		TmpUser = TmpUser->Next;
+	}
+}
+
diff -u -r --new-file linux/drivers/ha/event/event_core.c ha/drivers/ha/event/event_core.c
--- linux/drivers/ha/event/event_core.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/event/event_core.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,858 @@
+/*
+ * event_core.c
+ *
+ * Core intialization and driver access routines for the eventing mechanism.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/event.h>
+#include <linux/proc_fs.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "event_core.h"
+
+#define MODVERSIONS
+
+/* Linux Driver prototypes. */
+static int event_ioctl(struct inode *, struct file *, unsigned int, unsigned long);
+static int event_open(struct inode *, struct file *);
+static int event_release(struct inode *, struct file *);
+static int event_fasync(int, struct file *, int);
+
+static struct  file_operations event_fops = {
+	ioctl:    event_ioctl,
+	open:     event_open,
+	release:  event_release,
+	fasync:   event_fasync,
+};
+
+int  EventUserSubscribeEventByType(UserEventInfo *, EventReq *);
+int  EventUserUnSubscribeEventByType(UserEventInfo *, EventReq *);
+int  EventUserSendEvent(UserEventInfo *, EventReq *);
+
+void EventFillFreeList(void);
+EventPacket *EventAllocate(void);
+spinlock_t EventAllocLock = SPIN_LOCK_UNLOCKED;
+
+KernelClassInfo KernelClassHash[NUM_EVENT_HASHES];
+
+EventPacket *EventFreeList;
+
+int EventMajor;
+
+#ifdef CONFIG_PROC_FS
+/* /proc entry routines. */
+static int EventUserReadProc(char *, char **, off_t, int);
+static int EventEventsReadProc(char *, char **, off_t, int);
+
+struct proc_dir_entry *EventProcDir;
+#endif
+
+int             
+event_init(void)
+{
+	int loop;
+
+	printk("Initializing the eventing mechanism\n");
+
+	for (loop = 0; loop < NUM_EVENT_HASHES; loop++) {
+		KernelClassHash[loop].Lock = SPIN_LOCK_UNLOCKED;
+		KernelClassHash[loop].Next = NULL;
+	}
+
+	/* Event packets will be often used and reused,  To prevent memory
+	 * fragmentation a bucket of them will be allocated 1 page memory
+	 * usage at a time and placed on a free list.  If the list gets empty
+	 * a new bucket will be allocated in addition.
+	 */
+	EventFillFreeList();
+
+	if ((EventMajor = register_chrdev(0, "Event Manager", &event_fops)) < 0) {
+		printk("Cound not register the event manager\n");
+		return -ENODEV;
+	}
+
+#ifdef CONFIG_PROC_FS
+	EventProcDir = proc_mkdir("events", NULL);
+	EventProcDir->owner = THIS_MODULE;
+	create_proc_info_entry("users", 0, EventProcDir, EventUserReadProc);
+	create_proc_info_entry("events", 0, EventProcDir, EventEventsReadProc);
+#endif
+	return 0;
+}
+
+/* Linux Driver prototypes. */
+static int
+event_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+{
+	EventReq EventInfo;
+	UserEventInfo *UserInfo = (UserEventInfo *)file->private_data;
+	EventIdPacket EventId;
+	EventPacket Packet;
+	EventPacket *TmpPacket;
+	char *TmpString = NULL;
+	int RetVal;
+	void *FreeData;
+
+	switch (cmd) {
+	case EVENT_REG_ID:
+		if (UserInfo->Id != 0) {
+			return -EBUSY;
+		}
+
+		if (copy_from_user((int *)&EventId, (void *)arg, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+
+		EventId.Id = EventRegisterId(EventId.IdString);
+		UserInfo->Id = EventId.Id;
+
+		if (copy_to_user((void *)arg, (int *)&EventId, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+		return 0;
+
+	case EVENT_UNREG_ID:
+		if (UserInfo->Id == 0) {
+			return -ENOENT;
+		}
+
+		if (copy_from_user((int *)&EventId, (void *)arg, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+
+		UserInfo->Id = 0;
+		return EventUnRegisterId(EventId.Id);
+
+	case EVENT_GET_ID:
+		if (copy_from_user((int *)&EventId, (void *)arg, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+
+		if ((EventId.Id = EventGetId(EventId.IdString)) < 0) {
+			return EventId.Id;
+		}
+
+		if (copy_to_user((void *)arg, (int *)&EventId, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+		return 0;
+
+	case EVENT_GET_ID_STRING:
+		if (copy_from_user((int *)&EventId, (void *)arg, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+
+		if ((RetVal = EventGetIdString(EventId.Id, EventId.IdString)) <0) {
+			return RetVal;
+		}
+
+		if (copy_to_user((void *)arg, (int *)&EventId, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+		return 0;
+
+	case EVENT_REG_EVENT_CLASS:
+		if (copy_from_user((int *)&EventId, (void *)arg, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+
+		if ((RetVal = EventRegisterEventClass(EventId.IdString, &EventId.Id)) == -ENOSPC) {
+			return RetVal;
+		}
+
+		if (copy_to_user((void *)arg, (int *)&EventId, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+		return RetVal;
+
+	case EVENT_UNREG_EVENT_CLASS:
+		return EventUnRegisterEventClass(arg);
+
+	case EVENT_GET_EVENT_CLASS:
+		if (copy_from_user((int *)&EventId, (void *)arg, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+
+		if ((EventId.Id = EventGetEventClass(EventId.IdString)) < 0) {
+			return EventId.Id;
+		}
+
+		if (copy_to_user((void *)arg, (int *)&EventId, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+		return 0;
+
+	case EVENT_GET_EVENT_CLASS_STRING:
+		if (copy_from_user((int *)&EventId, (void *)arg, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+
+		if ((RetVal = EventGetEventClassString(EventId.Id, EventId.IdString)) < 0) {
+			return RetVal;
+		}
+
+		if (copy_to_user((void *)arg, (int *)&EventId, sizeof(EventIdPacket))) {
+			return -EFAULT;
+		}
+		return 0;
+
+	case EVENT_SUBSCRIBE_EVENT_BY_TYPE:
+		if (copy_from_user((int *)&EventInfo, (void *)arg, sizeof(EventReq))) {
+			return -EFAULT;
+		}
+
+		return EventUserSubscribeEventByType(UserInfo, &EventInfo);
+
+	case EVENT_UNSUBSCRIBE_EVENT_BY_TYPE:
+		if (copy_from_user((int *)&EventInfo, (void *)arg, sizeof(EventReq))) {
+			return -EFAULT;
+		}
+
+		return EventUserUnSubscribeEventByType(UserInfo, &EventInfo);
+
+	case EVENT_SUBSCRIBE_EVENT_BY_CLASS:
+		EventInfo.Id = UserInfo->Id;
+		EventInfo.Pri = 1;
+		EventInfo.Class = (int)arg;
+		EventInfo.Event = 0;
+		return EventUserSubscribeEventByType(UserInfo, &EventInfo);
+
+	case EVENT_UNSUBSCRIBE_EVENT_BY_CLASS:
+		EventInfo.Id = UserInfo->Id;
+		EventInfo.Pri = 1;
+		EventInfo.Class = (int)arg;
+		EventInfo.Event = 0;
+		return EventUserUnSubscribeEventByType(UserInfo, &EventInfo);
+
+	case EVENT_SEND_EVENT:
+		if (copy_from_user((int *)&Packet, (void *)arg, sizeof(EventPacket))) {
+			return -EFAULT;
+		}
+
+		if ((Packet.DataLen != 0) && (Packet.Data != NULL)) {
+			TmpString = kmalloc(Packet.DataLen + 1, GFP_KERNEL);
+
+			if (copy_from_user((int *)TmpString, (void *)Packet.Data, Packet.DataLen)) {
+				return -ENXIO;
+			}
+		}
+
+		return EventSendEvent(Packet.Id, Packet.Pri,
+				      Packet.Class, Packet.Event,
+				      Packet.Info[0], Packet.Info[1],
+				      Packet.Info[2], Packet.Info[3],
+				      Packet.DataLen, TmpString);
+
+	case EVENT_GET_EVENT:
+		if (copy_from_user((int *)&Packet, (void *)arg, sizeof(EventPacket))) {
+			return -EFAULT;
+		}
+
+		/* While wait for event is indicated and this is a polled device. */
+		do {
+			unsigned long flags;
+
+			spin_lock_irqsave(&UserInfo->Lock, flags);
+			TmpPacket = UserInfo->Head;
+
+			if (TmpPacket) {
+				if ((TmpPacket->DataLen != 0) && (TmpPacket->Data != NULL) &&
+			    		(Packet.Data != NULL)) {
+					if (Packet.DataLen < TmpPacket->DataLen) {
+						TmpPacket->DataLen = Packet.DataLen;
+					}
+
+					if (copy_to_user((void *)Packet.Data, (int *)TmpPacket->Data,
+							TmpPacket->DataLen)) {
+						spin_unlock_irqrestore(&UserInfo->Lock, flags);
+						return -ENXIO;
+					}
+					FreeData = TmpPacket->Data;
+					TmpPacket->Data = Packet.Data;
+	
+					kfree(FreeData);
+				}
+
+				if (copy_to_user((void *)arg, (int *)TmpPacket,
+							sizeof(EventPacket))) {
+					spin_unlock_irqrestore(&UserInfo->Lock, flags);
+					return -EFAULT;
+				}
+				UserInfo->Head = TmpPacket->Next;
+				if (UserInfo->Head == NULL) {
+					UserInfo->Tail = NULL;
+				}
+
+				spin_unlock_irqrestore(&UserInfo->Lock, flags);
+				EventFree(TmpPacket, 0);
+				return 0;
+			} 
+			if (!Packet.Flag) {
+				spin_unlock_irqrestore(&UserInfo->Lock, flags);
+				return -EAGAIN;
+			}
+
+			spin_unlock_irqrestore(&UserInfo->Lock, flags);
+			interruptible_sleep_on(&UserInfo->WaitQ);
+			spin_lock_irqsave(&UserInfo->Lock, flags);
+
+			if (UserInfo->Head == NULL) {
+				spin_unlock_irqrestore(&UserInfo->Lock, flags);
+				return -EINTR;
+			}
+		} while (Packet.Flag);
+	default:
+		return -EINVAL;
+	}
+}
+
+static int
+event_open(struct inode *inode, struct file *file)
+{
+	UserEventInfo *UserInfo = (UserEventInfo *)kmalloc(sizeof(UserEventInfo), GFP_KERNEL);
+
+	UserInfo->Id = 0;
+	UserInfo->Type = ED_USER_POLL;
+	init_waitqueue_head(&UserInfo->WaitQ);
+	UserInfo->FasyncPtr = (struct fasync_struct *)NULL;
+	UserInfo->Head = (EventPacket *)NULL;
+	UserInfo->Tail = (EventPacket *)NULL;
+	UserInfo->Lock = SPIN_LOCK_UNLOCKED;
+
+	file->private_data = (void *)UserInfo;
+	return 0;
+}
+
+static int
+event_release(struct inode *inode, struct file *file)
+{
+	EventPacket *Tmp1EventPtr;
+	EventPacket *Tmp2EventPtr;
+	UserEventInfo *UserInfo = (UserEventInfo *)file->private_data;
+
+	/* It the user had registered an ID then get his information
+	 * out of the system.
+	 */
+	if (UserInfo->Id != 0) {
+		EventUnRegisterId(UserInfo->Id);
+
+		/* Free any pending events scheduled for this user. */
+		Tmp1EventPtr = UserInfo->Head;
+		while (Tmp1EventPtr) {
+			Tmp2EventPtr = Tmp1EventPtr;
+			Tmp1EventPtr = Tmp1EventPtr->Next;
+			EventFree(Tmp2EventPtr, 1);
+		}
+	}
+
+	/* Make him gone. */
+	kfree(UserInfo);
+	return 0;
+}
+
+static int
+event_fasync(int fd, struct file *fp, int on)
+{
+	unsigned long flags;
+	UserEventInfo *UserInfo = (UserEventInfo *)fp->private_data;
+
+	spin_lock_irqsave(&UserInfo->Lock, flags);
+	fasync_helper(fd, fp, on, &UserInfo->FasyncPtr);
+
+	if (on) {
+		UserInfo->Type = ED_USER_ASYNC;
+	} else {
+		UserInfo->Type = ED_USER_POLL;
+	}
+
+	spin_unlock_irqrestore(&UserInfo->Lock, flags);
+	return 0;
+}
+
+#ifdef CONFIG_PROC_FS
+static int
+EventUserReadProc(char * buf, char ** start, off_t offset, int len)
+{
+	char *Page = buf;
+	KernelUserInfo *TmpUser;
+	unsigned long flags;
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	TmpUser = KernelUsersHead;
+	Page += sprintf(Page, "\nEvent Users List\n");
+	Page += sprintf(Page, "------------------------------\n");
+	while (TmpUser) {
+		Page += sprintf(Page, "%3d: %s\n", TmpUser->Id, TmpUser->IdString);
+		TmpUser = TmpUser->Next;
+	}
+		
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	Page += sprintf(Page, "\n");
+
+	return (int)(Page - buf);
+}
+
+static int
+EventEventsReadProc(char * buf, char ** start, off_t offset, int len)
+{
+	int Hash;
+	KernelClassInfo *HashBase;
+	EventDestBase *EventBase;
+	EventDest *Dest;
+	EventPacket *Packet;
+	char *Page = buf;
+	char Scratch[64];
+
+	Page += sprintf(Page, "\nDump Class List:\n");
+	Page += sprintf(Page, "------------------------------\n");
+	for (Hash = 0; Hash < NUM_EVENT_HASHES; Hash++) {
+		HashBase = &KernelClassHash[Hash];
+
+		while (HashBase->Next) {
+			Page += sprintf(Page, "Class %d Name \"%s\" Use %d\n",
+				HashBase->Class, HashBase->ClassString,
+				HashBase->UseCount);
+
+			EventBase = HashBase->EventQ;
+			while (EventBase->Next != NULL) {
+				Page += sprintf(Page, "    Event %d count %d\n",
+					EventBase->Event, EventBase->UseCount);
+
+				Dest = &EventBase->DestQ;
+				while (Dest->Next != NULL) {
+					EventGetIdString(Dest->Id, Scratch);
+					Page += sprintf(Page, "        User %d \"%s\" Priority %d ",
+					Dest->Id, Scratch, Dest->Pri);
+
+					if (Dest->UserInfo) {
+						Page += sprintf(Page, "User Application\n");
+						Packet = Dest->UserInfo->Head;
+
+						while (Packet) {
+							Page += sprintf(Page, "Sender %d info 0x%x:0x%x:0x%x:0x%x data len %d\n",
+								Packet->Id, Packet->Info[0], Packet->Info[1], Packet->Info[2], Packet->Info[3], Packet->DataLen);
+						}
+					} else if (Dest->KernelCB) {
+						Page += sprintf(Page, "Kernel Call Back\n");
+					} else {
+						Page += sprintf(Page, "Kernel Queued\n");
+						Packet = Dest->KernelInfo->Head;
+
+						while (Packet) {
+							Page += sprintf(Page, "Sender %d info 0x%x:0x%x:0x%x:0x%x data len %d\n",
+								Packet->Id, Packet->Info[0], Packet->Info[1], Packet->Info[2], Packet->Info[3], Packet->DataLen);
+						}
+					}
+
+					Dest = Dest->Next;
+				}
+
+				EventBase = EventBase->Next;
+			}
+
+			HashBase = HashBase->Next;
+		}
+	}
+	return (int)(Page - buf);
+}
+#endif
+
+void
+EventFillFreeList(void)
+{
+	int loop;
+	EventPacket *TmpBase;
+
+	EventFreeList = kmalloc(4096, GFP_KERNEL);
+	TmpBase = EventFreeList;
+
+	for (loop = 0; loop < (4096 / sizeof(EventPacket))-1; loop++) {
+		TmpBase->Event = 0;
+		TmpBase->Class = 0;
+		TmpBase->TimeStamp.tv_sec = 0;
+		TmpBase->TimeStamp.tv_usec = 0;
+		TmpBase->Info[0] = 0;
+		TmpBase->Info[1] = 0;
+		TmpBase->Info[2] = 0;
+		TmpBase->Info[3] = 0;
+		TmpBase->Pri = 0;
+		TmpBase->DataLen = 0;
+		TmpBase->Data = NULL;
+		TmpBase->Next = TmpBase + 1;
+		TmpBase++;
+	}
+	TmpBase->Event = 0;
+	TmpBase->Class = 0;
+	TmpBase->TimeStamp.tv_sec = 0;
+	TmpBase->TimeStamp.tv_usec = 0;
+	TmpBase->Info[0] = 0;
+	TmpBase->Info[1] = 0;
+	TmpBase->Info[2] = 0;
+	TmpBase->Info[3] = 0;
+	TmpBase->Pri = 0;
+	TmpBase->DataLen = 0;
+	TmpBase->Data = NULL;
+	TmpBase->Next = NULL;
+}
+
+EventPacket *
+EventAllocate(void)
+{
+	EventPacket *TmpBase;
+
+	spin_lock(&EventAllocLock);
+	TmpBase = EventFreeList;
+	if ((TmpBase = kmalloc(sizeof(EventPacket), GFP_KERNEL)) != NULL) {
+		/* Still enough memory to not worry about using it. */
+		TmpBase->Flag = 0;
+		spin_unlock(&EventAllocLock);
+		return  TmpBase;
+	}
+
+	/* Get a packet from the reserved list. */
+	TmpBase = EventFreeList;
+	EventFreeList = EventFreeList->Next;
+	TmpBase->Flag = EF_EMERGENCY_PACKET;
+
+	if (EventFreeList == NULL) {
+		EventFillFreeList();
+	}
+
+	spin_unlock(&EventAllocLock);
+	return TmpBase;
+}
+
+void
+EventFree(EventPacket *eventPtr, int flag)
+{
+	unsigned long flags;
+
+	spin_lock_irqsave(&EventAllocLock, flags);
+	if (flag && (eventPtr->DataLen > 0) && (eventPtr->Data != NULL)) {
+		kfree(eventPtr->Data);
+	}
+
+	if (eventPtr->Flag & EF_EMERGENCY_PACKET) {
+		eventPtr->Next = EventFreeList;
+		EventFreeList = eventPtr;
+	} else {
+		kfree(eventPtr);
+	}
+
+	spin_unlock_irqrestore(&EventAllocLock, flags);
+	return;
+}
+
+void
+EventGenEvent(int id, int pri, int class, int event,
+	      int info0, int info1, int info2, int info3,
+	      EventDest *EventDestP, int dataLen, void *data)
+{
+	EventPacket *Packet;
+	EventPacket *TmpPacket;
+	EventPacket *EndPacket;
+
+	Packet = EventAllocate();
+
+	Packet->Id = id;
+	Packet->Pri = pri;
+	Packet->Class = class;
+	Packet->Event = event;
+	do_gettimeofday(&Packet->TimeStamp);
+	Packet->Info[0] = info0;
+	Packet->Info[1] = info1;
+	Packet->Info[2] = info2;
+	Packet->Info[3] = info3;
+	Packet->DataLen = dataLen;
+
+	if ((dataLen != 0) && (data != NULL)) {
+		if ((Packet->Data = kmalloc(dataLen + 1, GFP_KERNEL)) == NULL) {
+			Packet->DataLen = 0;
+			Packet->Data = NULL;
+			Packet->Flag |= EF_DATA_FAILURE;
+		} else {
+			strncpy(Packet->Data, data, dataLen);
+			Packet->Flag |= EF_DATA_AVAIL;
+		}
+	} else {
+		Packet->Data = NULL;
+		Packet->Flag &= ~(EF_DATA_AVAIL|EF_DATA_FAILURE);
+	}
+
+	if (EventDestP->UserInfo == NULL) {
+		/* Queue in kernel */
+		spin_lock(&EventDestP->KernelInfo->Lock);
+		TmpPacket = EventDestP->KernelInfo->Head;
+		EndPacket = EventDestP->KernelInfo->Tail;
+
+		if ((TmpPacket == NULL) || (TmpPacket->Pri < pri)) {
+			/* Goes to head of the list. */
+			Packet->Next = TmpPacket;
+			EventDestP->KernelInfo->Head = Packet;
+		} else if (EndPacket->Pri >= pri) {
+			/* Place on tail of list */
+			EndPacket->Next = Packet;
+			Packet->Next = NULL;
+			EventDestP->KernelInfo->Tail = Packet;
+		} else {
+			/* Got to find the middle somewhere. */
+			while (TmpPacket) {
+				if (TmpPacket->Pri > pri) {
+					Packet->Next = TmpPacket->Next;
+					TmpPacket->Next = Packet;
+					break;
+				}
+				TmpPacket = TmpPacket->Next;
+			}
+		}
+
+		wake_up_interruptible(&EventDestP->KernelInfo->WaitQ);
+		spin_unlock(&EventDestP->KernelInfo->Lock);
+		return;
+	}
+
+	/* Send up to a processes */
+	spin_lock(&EventDestP->UserInfo->Lock);
+	TmpPacket = EventDestP->UserInfo->Head;
+	EndPacket = EventDestP->UserInfo->Tail;
+
+	if ((TmpPacket == NULL) || (TmpPacket->Pri < pri)) {
+		/* Goes to head of the list. */
+		Packet->Next = TmpPacket;
+		EventDestP->UserInfo->Head = Packet;
+		EventDestP->UserInfo->Tail = Packet;
+	} else if (EndPacket->Pri >= pri) {
+		/* Place on tail of list */
+		EndPacket->Next = Packet;
+		Packet->Next = NULL;
+		EventDestP->UserInfo->Tail = Packet;
+	} else {
+		/* Got to find the middle somewhere. */
+		while (TmpPacket) {
+			if (TmpPacket->Pri > pri) {
+				Packet->Next = TmpPacket->Next;
+				TmpPacket->Next = Packet;
+				break;
+			}
+			TmpPacket = TmpPacket->Next;
+		}
+	}
+
+	/* First check to see if this is polled file descriptor. */
+	if (EventDestP->UserInfo->Type == ED_USER_POLL) {
+		wake_up_interruptible(&EventDestP->UserInfo->WaitQ);
+		return;
+	}
+
+	wake_up_interruptible(&EventDestP->UserInfo->WaitQ);
+	kill_fasync(&EventDestP->UserInfo->FasyncPtr, SIGIO, POLL_IN);
+	spin_unlock(&EventDestP->UserInfo->Lock);
+	return;
+}
+
+int
+EventSendEvent(int id, int pri, int class, int event,
+	       int info0, int info1, int info2, int info3,
+	       int dataLen, void *data)
+{
+	EventDest *EventDestP = NULL;
+	EventDestBase *EventBase;
+	int EventTakers = 0;
+	unsigned long flags;
+	int Hash = class % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	if (EventCheckId(id) == NULL) {
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ENOENT;
+	}
+
+	spin_lock(&HashBase->Lock);
+
+	/* Find the top level entry for this class of events. */
+	if ((EventBase = EventFindEventBase(class, HashBase)) == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -EINVAL;
+	}
+
+	while (EventBase->Next != NULL) {
+		if ((EventBase->Event != event) &&
+		    (EventBase->Event != 0)) {
+			EventBase = EventBase->Next;
+			continue;
+		}
+
+		EventDestP = &EventBase->DestQ;
+
+		while (EventDestP->Next != NULL) {
+			EventTakers++;
+			if (EventDestP->KernelCB != NULL) {
+				if ((*EventDestP->KernelCB)(id, pri, class,
+					event, info0, info1, info2, info3,
+					dataLen, data) == 0) {
+						kfree(data);
+				}
+			} else {
+				EventGenEvent(id, pri, class, event,
+					      info0, info1, info2, info3,
+					      EventDestP, dataLen, data);
+			}
+
+			EventDestP = EventDestP->Next;
+		}
+
+		EventBase = EventBase->Next;
+	}
+
+	spin_unlock(&HashBase->Lock);
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+
+	if (EventTakers) {
+		return 0;
+	}
+
+	return -ENXIO;
+}
+
+EventDestBase *
+EventFindEventBase(int class, KernelClassInfo *HashBase)
+{
+	/* Find the top level entry for this class of events. */
+	while(HashBase->Next != NULL) {
+		if (HashBase->Class == class) {
+			break;
+		}
+		HashBase = HashBase->Next;
+	}
+
+	while(HashBase->Next == NULL) {
+		return NULL;
+	}
+
+	return HashBase->EventQ;
+}
+
+void
+EventUnReqAllEventsByClass(int id, EventDestBase *EventBase)
+{
+	EventDest *EventDestP = NULL;
+	EventDest *FreeDest = NULL;
+	EventDestBase *SaveBase = EventBase;
+	EventDestBase *LastEventBase = NULL;
+	
+	/* Search all event types in this class. */
+	while (EventBase->Next != NULL) {
+		EventDestP = &EventBase->DestQ;
+
+		/* Search the chain of destinations for this user. */
+		while (EventDestP->Next->Next != NULL) {
+			if (EventDestP->Next->Id == id) {
+				FreeDest = EventDestP->Next;
+				EventDestP->Next = EventDestP->Next->Next;
+				EventBase->UseCount--;
+				kfree(FreeDest);
+			} else {
+				EventDestP = EventDestP->Next;
+			}
+		}
+
+		/* Reset the top pointer */
+		EventDestP = &EventBase->DestQ;
+
+		/* Top element treated special. */
+		if (EventDestP->Id == id) {
+			EventDestP->UserInfo = EventDestP->Next->UserInfo;
+			EventDestP->KernelCB = EventDestP->Next->KernelCB;
+			EventDestP->Id = EventDestP->Next->Id;
+			EventDestP->KernelInfo = EventDestP->Next->KernelInfo;
+			FreeDest = EventDestP->Next;
+			EventDestP->Next = EventDestP->Next->Next;
+			EventBase->UseCount--;
+
+			kfree(FreeDest);
+		}
+
+		if (EventBase->UseCount == 0) {
+			if (EventBase == SaveBase) {
+				/* Free the top element */
+				EventBase->Event = EventBase->Next->Event;
+				EventBase->UseCount = EventBase->Next->UseCount;
+				EventBase->DestQ = EventBase->Next->DestQ;
+				LastEventBase = EventBase->Next;
+				EventBase->Next = LastEventBase->Next;
+				kfree(LastEventBase);
+			} else {
+				LastEventBase->Next = EventBase->Next;
+				kfree(EventBase);
+				EventBase = LastEventBase->Next;
+			}
+		} else {
+			/* Go to the next event type. */
+			LastEventBase = EventBase;
+			EventBase = EventBase->Next;
+		}
+	}
+
+	return;
+}
+
+void
+EventUnReqAllEvents(int id)
+{
+	int hash;
+	KernelClassInfo *HashBase;
+
+	for (hash = 0; hash < NUM_EVENT_HASHES; hash++) {
+		HashBase = &KernelClassHash[hash];
+
+		spin_lock(&HashBase->Lock);
+		while(HashBase->Next != NULL) {
+			EventUnReqAllEventsByClass(id, HashBase->EventQ);
+			HashBase = HashBase->Next;
+		}
+		spin_unlock(&HashBase->Lock);
+	}
+
+	return;
+}
+
+EXPORT_SYMBOL(EventFree);
+EXPORT_SYMBOL(EventSendEvent);
diff -u -r --new-file linux/drivers/ha/event/event_core.h ha/drivers/ha/event/event_core.h
--- linux/drivers/ha/event/event_core.h	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/event/event_core.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,103 @@
+/*
+ * event_core.h
+ *
+ * Data structures and values needed internaly for the eventing mechanism.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef EVENT_CORE_H
+#define EVENT_CORE_H
+
+/* Currently know types of event accesses. */
+#define ED_USER_ASYNC   1
+#define ED_USER_POLL    2
+
+
+typedef struct kernel_user_info {
+	int                     Id;
+	char                    IdString[16];
+        wait_queue_head_t       WaitQ;
+        EventPacket             *Head;
+        EventPacket             *Tail;
+	spinlock_t		Lock;
+	struct kernel_user_info *Next;
+} KernelUserInfo;
+
+typedef struct user_event_info {
+	int		     Type;
+	int		     Id;
+        wait_queue_head_t    WaitQ;
+        struct fasync_struct *FasyncPtr;
+        EventPacket          *Head;
+        EventPacket          *Tail;
+	spinlock_t	     Lock;
+} UserEventInfo;
+
+typedef struct event_destination {
+        int                      Pri;
+	int	                 Id;
+        int                      (*KernelCB)(int, int, int, int, int, int, int, int, int, void *);
+        UserEventInfo            *UserInfo;
+        KernelUserInfo           *KernelInfo;
+        struct event_destination *Next;
+} EventDest;
+
+typedef struct event_destination_base {
+        int           Event;
+        int           UseCount;
+        EventDest     DestQ;
+        struct event_destination_base *Next;
+} EventDestBase;
+
+typedef struct kernel_class_info {
+	int                     Class;
+	char                    ClassString[16];
+	int			UseCount;
+	EventDestBase           *EventQ;
+	spinlock_t		Lock;
+	struct kernel_class_info *Next;
+} KernelClassInfo;
+
+/* Kernel uses for the Flag in KernelEventPacket. */
+#define EF_EMERGENCY_PACKET     0x1
+
+#define NUM_EVENT_HASHES	10
+extern KernelClassInfo KernelClassHash[NUM_EVENT_HASHES];
+extern KernelUserInfo *KernelClassHead;
+extern KernelUserInfo *KernelUsersHead;
+
+extern rwlock_t KernelUsersLock;
+
+EventDestBase * EventFindEventBase(int class, KernelClassInfo *);
+KernelUserInfo *EventCheckId(int);
+void EventUnReqAllEvents(int);
+
+/* Debug routines. */
+void DumpEventReg(void);
+void DumpClassList(void);
+#endif /* EVENT_CORE_H */
diff -u -r --new-file linux/drivers/ha/event/kernel_api.c ha/drivers/ha/event/kernel_api.c
--- linux/drivers/ha/event/kernel_api.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/event/kernel_api.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,690 @@
+/*
+ * kernel_api.c
+ *
+ * Interface routines for the eventing mechasism made available to
+ * other kernel code.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/event.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "event_core.h"
+
+#define MODVERSIONS
+
+int _EventGetEventClass(char *);
+
+KernelUserInfo *KernelUsersHead = NULL;
+unsigned int KernelNextId = 1;   /* Just so its not zero. */
+rwlock_t KernelUsersLock = RW_LOCK_UNLOCKED;
+
+KernelUserInfo *KernelClassHead = NULL;
+KernelUserInfo *KernelClassTail = NULL;
+unsigned int KernelNextClass = 1;   /* Just so its not zero. */
+spinlock_t ClassSearchLock = SPIN_LOCK_UNLOCKED;
+
+/*
+ * This is sort of equivelent to the user level open call.
+ */
+int
+EventRegisterId(char *idstring)
+{
+	KernelUserInfo *TmpUser;
+	unsigned long flags;
+
+	write_lock_irqsave(&KernelUsersLock, flags);
+
+	if (KernelUsersHead == NULL) {
+		if ((KernelUsersHead = kmalloc(sizeof(KernelUserInfo), GFP_KERNEL)) == NULL) {
+			/* System is in immenent danger of dying at this point. */
+			write_unlock_irqrestore(&KernelUsersLock, flags);
+			return -ENOSPC;
+		}
+		TmpUser = KernelUsersHead;
+	} else {
+		TmpUser = KernelUsersHead;
+
+		while (TmpUser->Next) {
+			TmpUser = TmpUser->Next;
+		}
+		if ((TmpUser->Next = kmalloc(sizeof(KernelUserInfo), GFP_KERNEL)) == NULL) {
+			/* System is in immenent danger of dying at this point. */
+			write_unlock_irqrestore(&KernelUsersLock, flags);
+			return -ENOSPC;
+		}
+		TmpUser = TmpUser->Next;
+	}
+
+	TmpUser->Id = KernelNextId++;
+	strncpy(TmpUser->IdString, idstring, 16);
+	init_waitqueue_head(&TmpUser->WaitQ);
+	TmpUser->Head = NULL;
+	TmpUser->Tail = NULL;
+	TmpUser->Next = NULL;
+	TmpUser->Lock = SPIN_LOCK_UNLOCKED;
+
+	write_unlock_irqrestore(&KernelUsersLock, flags);
+
+	return TmpUser->Id;
+}
+
+int
+EventUnRegisterId(int id)
+{
+	KernelUserInfo *TmpUser;
+	KernelUserInfo *FreeUser;
+	unsigned long flags;
+
+	write_lock_irqsave(&KernelUsersLock, flags);
+
+	if (KernelUsersHead == NULL) {
+		write_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ENOENT;
+	}
+
+	if (KernelUsersHead->Id == id) {
+		FreeUser = KernelUsersHead;
+		KernelUsersHead = KernelUsersHead->Next;
+
+		spin_lock(&FreeUser->Lock);
+		write_unlock(&KernelUsersLock);
+		EventUnReqAllEvents(id);
+		spin_unlock_irqrestore(&FreeUser->Lock, flags);
+
+		kfree(FreeUser);
+
+		return 0;
+	}
+
+	TmpUser = KernelUsersHead;
+
+	while(TmpUser->Next) {
+		if (TmpUser->Next->Id == id) {
+			FreeUser = TmpUser->Next;
+			TmpUser->Next = FreeUser->Next;
+
+			spin_lock(&FreeUser->Lock);
+			write_unlock(&KernelUsersLock);
+			EventUnReqAllEvents(id);
+			spin_unlock_irqrestore(&FreeUser->Lock, flags);
+
+			kfree(FreeUser);
+
+			return 0;
+		}
+		TmpUser = TmpUser->Next;
+	}
+
+	write_unlock_irqrestore(&KernelUsersLock, flags);
+	return -ESRCH;
+}
+
+int
+EventGetId(char *idstring)
+{
+	KernelUserInfo *TmpUser;
+	unsigned long flags;
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	TmpUser = KernelUsersHead;
+
+	while (TmpUser) {
+		if (!strcmp(TmpUser->IdString, idstring)) {
+			read_unlock_irqrestore(&KernelUsersLock, flags);
+			return TmpUser->Id;
+		}
+		TmpUser = TmpUser->Next;
+	}
+
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return -ESRCH;
+}
+
+int
+EventGetIdString(int id, char *idstring)
+{
+	KernelUserInfo *TmpUser;
+	unsigned long flags;
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	TmpUser = KernelUsersHead;
+
+	while (TmpUser) {
+		if (TmpUser->Id == id) {
+			strncpy(idstring, TmpUser->IdString, 16);
+			read_unlock_irqrestore(&KernelUsersLock, flags);
+			return 0;
+		}
+		TmpUser = TmpUser->Next;
+	}
+
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return -ESRCH;
+}
+
+KernelUserInfo *
+EventCheckId(int id)
+{
+	KernelUserInfo *TmpUser;
+
+	TmpUser = KernelUsersHead;
+
+	while (TmpUser) {
+		if (TmpUser->Id == id) {
+			return TmpUser;
+		}
+		TmpUser = TmpUser->Next;
+	}
+
+	return NULL;
+}
+
+int
+EventFillInHashInfo(KernelClassInfo *HashBase, char *classString, int *class)
+{
+	HashBase->Class = KernelNextClass++;
+	strncpy(HashBase->ClassString, classString, 16);
+
+	if ((HashBase->EventQ = kmalloc(sizeof(EventDestBase), GFP_KERNEL)) == NULL) {
+		return -ENOSPC;
+	}
+
+	HashBase->EventQ->Next = NULL;
+
+	if ((HashBase->Next = kmalloc(sizeof(KernelClassInfo), GFP_KERNEL)) == NULL) {
+		kfree(HashBase->EventQ);
+		HashBase->EventQ = NULL;
+		return -ENOSPC;
+	}
+
+	HashBase->Next->Next = NULL;
+	HashBase->UseCount = 0;
+
+	*class = HashBase->Class;
+	return 0;
+}
+
+int
+EventRegisterEventClass(char *classString, int *class)
+{
+	int RetVal;
+	unsigned long flags;
+	int Hash = KernelNextClass % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+
+	spin_lock_irqsave(&ClassSearchLock, flags);
+	/* First search all classes to find out if it already exists */
+	if ((*class = _EventGetEventClass(classString)) > 0) {
+		spin_unlock_irqrestore(&ClassSearchLock, flags);
+		return -EBUSY;
+	}
+
+	spin_lock(&HashBase->Lock);
+
+	while (HashBase->Next != NULL) {
+		HashBase = HashBase->Next;
+	}
+
+	RetVal = EventFillInHashInfo(HashBase, classString, class);
+	spin_unlock(&HashBase->Lock);
+	spin_unlock_irqrestore(&ClassSearchLock, flags);
+	return RetVal;
+}
+
+int
+EventUnRegisterEventClass(int class)
+{
+	unsigned long flags;
+	int Hash = class % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+	KernelClassInfo* HashDel;
+
+	spin_lock_irqsave(&ClassSearchLock, flags);
+	if (HashBase->Next == NULL) {
+		spin_unlock_irqrestore(&ClassSearchLock, flags);
+		return -ESRCH;
+	}
+
+	spin_lock(&HashBase->Lock);
+
+	if (HashBase->Class == class) {
+		if (HashBase->UseCount != 0) {
+			spin_unlock(&HashBase->Lock);
+			spin_unlock_irqrestore(&ClassSearchLock, flags);
+			return -EBUSY;
+		}
+
+		HashDel = HashBase->Next;
+
+		goto EventDelHashInfo;
+	}
+
+	HashDel = HashBase->Next;
+
+	while(HashDel->Next != NULL) {
+		if (HashDel->Class == class) {
+			break;
+		}
+		HashBase = HashDel;
+		HashDel = HashDel->Next;
+	}
+
+	if (HashDel->Next == NULL) {
+		spin_unlock(&HashBase->Lock);
+		spin_unlock_irqrestore(&ClassSearchLock, flags);
+		return -ESRCH;
+	}
+
+	if (HashDel->UseCount != 0) {
+		spin_unlock(&HashBase->Lock);
+		spin_unlock_irqrestore(&ClassSearchLock, flags);
+		return -EBUSY;
+	}
+
+
+EventDelHashInfo:
+	kfree(HashBase->EventQ);
+
+	HashBase->Class = HashDel->Class;
+	strncpy(HashBase->ClassString, HashDel->ClassString, 16);
+	HashBase->EventQ = HashDel->EventQ;
+	HashBase->Next = HashDel->Next;
+	HashBase->UseCount--;
+
+	kfree(HashDel);
+	spin_unlock(&HashBase->Lock);
+	spin_unlock_irqrestore(&ClassSearchLock, flags);
+	return 0;
+}
+
+int
+EventGetEventClass(char *classString)
+{
+	int RetVal;
+	unsigned long flags;
+
+	spin_lock_irqsave(&ClassSearchLock, flags);
+	RetVal = _EventGetEventClass(classString);
+	spin_unlock_irqrestore(&ClassSearchLock, flags);
+	return RetVal;
+}
+
+int
+_EventGetEventClass(char *classString)
+{
+	int Hash;
+	unsigned long flags;
+	KernelClassInfo *HashBase;
+
+	for (Hash = 0; Hash < NUM_EVENT_HASHES; Hash++) {
+		HashBase = &KernelClassHash[Hash];
+
+		spin_lock_irqsave(&HashBase->Lock, flags);
+		while (HashBase->Next) {
+			if (!strcmp(HashBase->ClassString, classString)) {
+				spin_unlock_irqrestore(&HashBase->Lock, flags);
+				return HashBase->Class;
+			}
+			HashBase = HashBase->Next;
+		}
+		spin_unlock_irqrestore(&HashBase->Lock, flags);
+	}
+
+	return -ESRCH;
+}
+
+int
+EventGetEventClassString(int class, char *classString)
+{
+	int Hash = class % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+	unsigned long flags;
+
+	spin_lock_irqsave(&HashBase->Lock, flags);
+	while (HashBase->Next) {
+		if (HashBase->Class == class) {
+			strncpy(classString, HashBase->ClassString, 16);
+			spin_unlock_irqrestore(&HashBase->Lock, flags);
+			return 0;
+		}
+		HashBase = HashBase->Next;
+	}
+
+	spin_unlock_irqrestore(&HashBase->Lock, flags);
+	return -ESRCH;
+}
+
+int
+EventSubscribeEventByType(int id, int pri, int class, int event,
+	            int (*kernelCB)(int, int, int, int, int, int, int, int, int, void *))
+{
+	EventDest *EventDestP = NULL;
+	EventDest *TmpDestP = NULL;
+	EventDest *LastEventDestP = NULL;
+	EventDestBase *EventBase;
+	KernelUserInfo *EventUser;
+	int Hash = class % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+	unsigned long flags;
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	if ((EventUser = EventCheckId(id)) == NULL) {
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ESRCH;
+	}
+
+	spin_lock(&HashBase->Lock);
+
+	/* Find the top level entry for this class of events. */
+	if ((EventBase = EventFindEventBase(class, HashBase)) == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -EINVAL;
+	}
+
+	/* search until the event is found in this catagory or until the
+	 * last blank element on the list if found.
+	 */
+	while (EventBase->Next != NULL) {
+		if (EventBase->Event == event) {
+			EventDestP = &EventBase->DestQ;
+			break;
+		}
+		EventBase = EventBase->Next;
+	}
+
+	/* If not destination pointer has been identified for a chain
+	 * search then this event type has not yet been registered by anybody
+	 * so fill in the last empty list element and create a new empty one
+	 * to inidcate end of list.
+	 */
+	if (EventDestP == NULL) {
+		EventBase->Event = event;
+		EventBase->UseCount = 0;
+
+		/* Create the next empty element to indicate end of list. */
+		if ((EventBase->Next = kmalloc(sizeof(EventDestBase), GFP_KERNEL)) == NULL) {
+			spin_unlock(&HashBase->Lock);
+			read_unlock_irqrestore(&KernelUsersLock, flags);
+			return -ENOSPC;
+		}
+
+		EventBase->Next->Next = NULL;
+
+		EventDestP = &EventBase->DestQ;
+		EventDestP->Next = NULL;
+
+		 goto EventFillInKernelRequestPacket;
+	}
+
+	/* Now search to see if this file descriptor already has registered
+	 * for this event type.
+	 */
+	while (EventDestP->Next != NULL) {
+		if (EventDestP->Id == id) {
+			spin_unlock(&HashBase->Lock);
+			read_unlock_irqrestore(&KernelUsersLock, flags);
+			return -EBUSY;
+				
+		}
+
+		LastEventDestP = EventDestP;
+		EventDestP = EventDestP->Next;
+	}
+
+	/* Now record the destination and create a new empty element to 
+	 * indicate end of list.
+	 */
+
+	/* Most registrations go at the end of the list. */
+	if ((LastEventDestP != NULL) && (LastEventDestP->Pri >= pri)) {
+		if ((EventDestP->Next = kmalloc(sizeof(EventDest), GFP_KERNEL)) == NULL) {
+			spin_unlock(&HashBase->Lock);
+			read_unlock_irqrestore(&KernelUsersLock, flags);
+			return -ENOSPC;
+		}
+
+		EventDestP->Next->Next = NULL;
+		goto EventFillInKernelRequestPacket;
+	}
+
+	EventDestP = &EventBase->DestQ;
+
+	/* Check the priority against the top element */
+	if (EventDestP->Pri >= pri) {
+		/* Priority of event places it somewhere in the middle */
+		while (EventDestP->Next->Pri >= pri) {
+			EventDestP = EventDestP->Next;
+		}
+	}
+
+	if ((TmpDestP = kmalloc(sizeof(EventDest), GFP_KERNEL)) == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ENOSPC;
+	}
+
+	TmpDestP->Pri = EventDestP->Pri;
+	TmpDestP->UserInfo = EventDestP->UserInfo;
+	TmpDestP->KernelCB = EventDestP->KernelCB;
+	TmpDestP->Id = EventDestP->Id;
+	TmpDestP->KernelInfo = EventDestP->KernelInfo;
+	TmpDestP->Next = EventDestP->Next;
+	EventDestP->Next = TmpDestP;
+
+EventFillInKernelRequestPacket:
+	EventBase->UseCount++;
+	EventDestP->Pri = pri;
+	EventDestP->UserInfo = NULL;
+	EventDestP->Id = id;
+	EventDestP->KernelCB = kernelCB;
+	EventDestP->KernelInfo = EventUser;
+
+	spin_unlock(&HashBase->Lock);
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return 0;
+}
+
+int
+EventUnSubscribeEventByType(int id, int class, int event)
+{
+	EventDest *EventDestP = NULL;
+	EventDest *FreeDest = NULL;
+	EventDestBase *EventBase;
+	EventDestBase *LastEventBase = NULL;
+	KernelUserInfo *EventUser;
+	int Hash = class % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+	unsigned long flags;
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	if ((EventUser = EventCheckId(id)) == NULL) {
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ENOENT;
+	}
+
+	spin_lock_irqsave(&HashBase->Lock, flags);
+
+	/* Find the top level entry for this class of events. */
+	if ((EventBase = EventFindEventBase(class, HashBase)) == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -EINVAL;
+	}
+
+	/* search until the event is found in this catagory or until the
+	 * last blank element on the list if found.
+	 */
+	while (EventBase->Next != NULL) {
+		if (EventBase->Event == event) {
+			EventDestP = &EventBase->DestQ;
+			break;
+		}
+
+		LastEventBase = EventBase;
+		EventBase = EventBase->Next;
+	}
+
+	/* If event type not found then the user process was obviously not
+	 * registered for this event.
+	 */
+	if (EventDestP == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ESRCH;
+	}
+
+	if (EventDestP->Id == id) {
+		EventDestP->UserInfo = EventDestP->Next->UserInfo;
+		EventDestP->KernelCB = EventDestP->Next->KernelCB;
+		EventDestP->Id = EventDestP->Next->Id;
+		EventDestP->KernelInfo = EventDestP->Next->KernelInfo;
+		FreeDest = EventDestP->Next;
+		EventDestP->Next = EventDestP->Next->Next;
+
+		goto EventUnRegFreeBase;
+	}
+		
+	/* Allways search one ahead to help with single link list removal. */
+	while (EventDestP->Next->Next != NULL) {
+		if (EventDestP->Next->Id == id) {
+			FreeDest = EventDestP->Next;
+			EventDestP->Next = EventDestP->Next->Next;
+
+			goto EventUnRegFreeBase;
+		}
+		EventDestP = EventDestP->Next;
+	}
+
+	/* Entry not found in list. */
+	spin_unlock(&HashBase->Lock);
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return -ESRCH;
+
+EventUnRegFreeBase:
+	EventBase->UseCount--;
+
+	if (EventBase->UseCount == 0) {
+		/* Nobody is registered to receive this event. */
+		if (LastEventBase == NULL) {
+			/* Free the top element */
+			EventBase->Event = EventBase->Next->Event;
+			EventBase->UseCount = EventBase->Next->UseCount;
+			EventBase->DestQ = EventBase->Next->DestQ;
+			LastEventBase = EventBase->Next;
+			EventBase->Next = LastEventBase->Next;
+			kfree(LastEventBase);
+		} else {
+			LastEventBase->Next = EventBase->Next;
+			kfree(EventBase);
+		}
+	}
+
+	kfree(FreeDest);
+
+	spin_unlock(&HashBase->Lock);
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return 0;
+}
+
+int
+EventSubscribeEventByClass(int id, int pri, int class,
+		     int (*kernelCB)(int, int, int, int, int, int, int, int, int, void *))
+{
+	return EventSubscribeEventByType(id, pri, class, 0, kernelCB);
+}
+
+int
+EventUnSubscribeEventByClass(int id, int class)
+{
+	return EventUnSubscribeEventByType(id, class, 0);
+}
+
+int
+EventGetEvent(int id, int waitFlag, EventPacket *packet)
+{
+	EventPacket *TmpPacket;
+	KernelUserInfo *EventUser;
+	unsigned long flags;
+
+	for (;;) {
+		read_lock_irqsave(&KernelUsersLock, flags);
+		if ((EventUser = EventCheckId(id)) == NULL) {
+			read_unlock_irqrestore(&KernelUsersLock, flags);
+			packet = NULL;
+			return -ENOENT;
+		}
+
+		spin_lock(&EventUser->Lock);
+		read_unlock(&KernelUsersLock);
+		TmpPacket = EventUser->Head;
+
+		if (TmpPacket) {
+			EventUser->Head = TmpPacket->Next;
+			if (EventUser->Head == NULL) {
+				EventUser->Tail = NULL;
+			}
+			spin_unlock_irqrestore(&EventUser->Lock, flags);
+			packet = TmpPacket;
+			return 0;
+		}
+
+		if (!waitFlag) {
+			spin_unlock_irqrestore(&EventUser->Lock, flags);
+			packet = NULL;
+			return -EAGAIN;
+		}
+
+		spin_unlock_irqrestore(&EventUser->Lock, flags);
+		interruptible_sleep_on(&EventUser->WaitQ);
+	}
+}
+
+EXPORT_SYMBOL(EventRegisterId);
+EXPORT_SYMBOL(EventUnRegisterId);
+EXPORT_SYMBOL(EventGetId);
+EXPORT_SYMBOL(EventRegisterEventClass);
+EXPORT_SYMBOL(EventUnRegisterEventClass);
+EXPORT_SYMBOL(EventGetEventClass);
+EXPORT_SYMBOL(EventGetEventClassString);
+EXPORT_SYMBOL(EventSubscribeEventByType);
+EXPORT_SYMBOL(EventUnSubscribeEventByType);
+EXPORT_SYMBOL(EventSubscribeEventByClass);
+EXPORT_SYMBOL(EventUnSubscribeEventByClass);
+EXPORT_SYMBOL(EventGetEvent);
diff -u -r --new-file linux/drivers/ha/event/user_api.c ha/drivers/ha/event/user_api.c
--- linux/drivers/ha/event/user_api.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/ha/event/user_api.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,261 @@
+/*
+ * user_api.c
+ *
+ * User process interface routines for the eventing mechanism.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#include <linux/init.h>
+#include <linux/malloc.h>
+#include <linux/ioctl.h>
+#include <linux/wait.h>
+#include <linux/event.h>
+#include <linux/time.h>
+#include <asm/delay.h>
+#include <asm/io.h>
+#include <asm/uaccess.h>
+#include "event_core.h"
+
+int
+EventUserSubscribeEventByType(UserEventInfo* userInfo, EventReq *eventInfo)
+{
+	EventDest *EventDestP = NULL;
+	EventDest *TmpDestP = NULL;
+	EventDest *LastEventDestP = NULL;
+	EventDestBase *EventBase;
+	int Hash = eventInfo->Class % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+	unsigned long flags;
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	if (EventCheckId(eventInfo->Id) == NULL) {
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ENOENT;
+	}
+
+	spin_lock(&HashBase->Lock);
+
+	/* Find the top level entry for this class of events. */
+	if ((EventBase = EventFindEventBase(eventInfo->Class, HashBase)) == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ESRCH;
+	}
+
+	/* search until the event is found in this catagory or until the
+	 * last blank element on the list if found.
+	 */
+	while (EventBase->Next != NULL) {
+		if (EventBase->Event == eventInfo->Event) {
+			EventDestP = &EventBase->DestQ;
+			break;
+		}
+		EventBase = EventBase->Next;
+	}
+
+	/* If not destination pointer has been identified for a chain
+	 * search then this event type has not yet been registered by anybody
+	 * so fill in the last empty list element and create a new empty one
+	 * to inidcate end of list.
+	 */
+	if (EventDestP == NULL) {
+		EventBase->Event = eventInfo->Event;
+		EventBase->UseCount = 0;
+
+		/* Create the next empty element to indicate end of list. */
+		EventBase->Next = kmalloc(sizeof(EventDestBase), GFP_KERNEL);
+		EventBase->Next->Next = NULL;
+
+		EventDestP = &EventBase->DestQ;
+		EventDestP->Next = kmalloc(sizeof(EventDest), GFP_KERNEL);
+		EventDestP->Next->Next = NULL;
+
+		goto EventFillInRequestPacket;
+	}
+
+	/* Now search to see if this file descriptor already has registered
+	 * for this event type.
+	 */
+	while (EventDestP->Next != NULL) {
+		if (EventDestP->Id == eventInfo->Id) {
+			spin_unlock(&HashBase->Lock);
+			read_unlock_irqrestore(&KernelUsersLock, flags);
+			return -EBUSY;
+		}
+		LastEventDestP = EventDestP;
+		EventDestP = EventDestP->Next;
+	}
+
+	/* Now record the destination and create a new empty element to 
+	 * indicate end of list.
+	 */
+
+	/* Most registrations go at the end of the list. */
+	if ((LastEventDestP != NULL) && (LastEventDestP->Pri >= eventInfo->Pri)) {
+		EventDestP->Next = kmalloc(sizeof(EventDest), GFP_KERNEL);
+		EventDestP->Next->Next = NULL;
+		goto EventFillInRequestPacket;
+	}
+
+	/* Check the priority against the top element */
+	EventDestP = &EventBase->DestQ;
+	if (eventInfo->Pri <=  EventDestP->Pri) {
+		/* Priority of event places it somewhere in the middle */
+		while (EventDestP->Next->Pri >= eventInfo->Pri) {
+			EventDestP = EventDestP->Next;
+		}
+	}
+
+	TmpDestP = kmalloc(sizeof(EventDest), GFP_KERNEL);
+	TmpDestP->Pri = EventDestP->Pri;
+	TmpDestP->UserInfo = EventDestP->UserInfo;
+	TmpDestP->KernelCB = EventDestP->KernelCB;
+	TmpDestP->Id = EventDestP->Id;
+	TmpDestP->KernelInfo = EventDestP->KernelInfo;
+	TmpDestP->Next = EventDestP->Next;
+	EventDestP->Next = TmpDestP;
+
+EventFillInRequestPacket:
+	EventBase->UseCount++;
+	EventDestP->Pri = eventInfo->Pri;
+	EventDestP->UserInfo = userInfo;
+	EventDestP->KernelCB = NULL;
+	EventDestP->Id = userInfo->Id;
+	EventDestP->KernelInfo = NULL;
+
+	spin_unlock(&HashBase->Lock);
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return 0;
+}
+
+int
+EventUserUnSubscribeEventByType(UserEventInfo* userInfo, EventReq *eventInfo)
+{
+	EventDest *EventDestP = NULL;
+	EventDest *FreeDest = NULL;
+	EventDestBase *EventBase;
+	EventDestBase *LastEventBase = NULL;
+	int Hash = eventInfo->Class % NUM_EVENT_HASHES;
+	KernelClassInfo *HashBase = &KernelClassHash[Hash];
+	unsigned long flags;
+
+	read_lock_irqsave(&KernelUsersLock, flags);
+	if (EventCheckId(eventInfo->Id) == NULL) {
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ENOENT;
+	}
+
+	spin_lock(&HashBase->Lock);
+
+	/* Find the top level entry for this class of events. */
+	if ((EventBase = EventFindEventBase(eventInfo->Class, HashBase)) == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ESRCH;
+	}
+
+	/* search until the event is found in this catagory or until the
+	 * last blank element on the list if found.
+	 */
+	while (EventBase->Next != NULL) {
+		if (EventBase->Event == eventInfo->Event) {
+			EventDestP = &EventBase->DestQ;
+			break;
+		}
+
+		LastEventBase = EventBase;
+		EventBase = EventBase->Next;
+	}
+
+	/* If event type not found then the user process was obviously not
+	 * registered for this event.
+	 */
+	if (EventDestP == NULL) {
+		spin_unlock(&HashBase->Lock);
+		read_unlock_irqrestore(&KernelUsersLock, flags);
+		return -ESRCH;
+	}
+
+	/* Check the top element first */
+	if (EventDestP->Id == eventInfo->Id) {
+		EventDestP->UserInfo = EventDestP->Next->UserInfo;
+		EventDestP->KernelCB = EventDestP->Next->KernelCB;
+		EventDestP->Id = EventDestP->Next->Id;
+		EventDestP->KernelInfo = EventDestP->Next->KernelInfo;
+		FreeDest = EventDestP->Next;
+		EventDestP->Next = EventDestP->Next->Next;
+
+		goto EventUnRegFreeBase;
+	}
+		
+	/* Allways search one ahead to help with single link list removal. */
+	while (EventDestP->Next->Next != NULL) {
+		if (EventDestP->Next->Id == eventInfo->Id) {
+			FreeDest = EventDestP->Next;
+			EventDestP->Next = EventDestP->Next->Next;
+
+			goto EventUnRegFreeBase;
+		}
+		EventDestP = EventDestP->Next;
+	}
+
+	/* Entry not found in list. */
+	spin_unlock(&HashBase->Lock);
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return -ESRCH;
+
+EventUnRegFreeBase:
+	EventBase->UseCount--;
+
+	if (EventBase->UseCount == 0) {
+		/* Nobody is registered to receive this event. */
+		if (LastEventBase == NULL) {
+			/* Free the top element */
+			EventBase->Event = EventBase->Next->Event;
+			EventBase->UseCount = EventBase->Next->UseCount;
+			EventBase->DestQ = EventBase->Next->DestQ;
+			LastEventBase = EventBase->Next;
+			EventBase->Next = LastEventBase->Next;
+			kfree(LastEventBase);
+		} else {
+			LastEventBase->Next = EventBase->Next;
+			kfree(EventBase);
+		}
+	}
+
+	kfree(FreeDest);
+
+	spin_unlock(&HashBase->Lock);
+	read_unlock_irqrestore(&KernelUsersLock, flags);
+	return 0;
+}
diff -u -r --new-file linux/drivers/net/Config.in ha/drivers/net/Config.in
--- linux/drivers/net/Config.in	Mon Nov 19 16:19:42 2001
+++ ha/drivers/net/Config.in	Thu Dec 13 13:03:13 2001
@@ -160,6 +160,7 @@
       dep_tristate '    Apricot Xen-II on board Ethernet' CONFIG_APRICOT $CONFIG_ISA
       dep_tristate '    CS89x0 support' CONFIG_CS89x0 $CONFIG_ISA
       dep_tristate '    DECchip Tulip (dc21x4x) PCI support' CONFIG_TULIP $CONFIG_PCI
+      dep_mbool '      Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO $CONFIG_TULIP
       if [ "$CONFIG_TULIP" = "y" -o "$CONFIG_TULIP" = "m" ]; then
          dep_bool '      New bus configuration (EXPERIMENTAL)' CONFIG_TULIP_MWI $CONFIG_EXPERIMENTAL
          bool '      Use PCI shared mem for NIC registers' CONFIG_TULIP_MMIO
diff -u -r --new-file linux/drivers/net/eepro100.c ha/drivers/net/eepro100.c
--- linux/drivers/net/eepro100.c	Mon Nov 12 10:47:18 2001
+++ ha/drivers/net/eepro100.c	Thu Dec 13 13:03:13 2001
@@ -625,6 +625,7 @@
 	else
 		goto err_out_iounmap;
 
+	CpciRegisterDevice(pdev);
 	return 0;
 
 err_out_iounmap: ;
@@ -2258,6 +2259,8 @@
 						sp->tx_ring, sp->tx_ring_dma);
 	pci_disable_device(pdev);
 	kfree(dev);
+
+	CpciUnRegisterDevice(pdev);
 }
 
 static struct pci_device_id eepro100_pci_tbl[] __devinitdata = {
diff -u -r --new-file linux/drivers/net/tulip/tulip_core.c ha/drivers/net/tulip/tulip_core.c
--- linux/drivers/net/tulip/tulip_core.c	Mon Nov 19 16:19:42 2001
+++ ha/drivers/net/tulip/tulip_core.c	Thu Dec 13 13:03:13 2001
@@ -1801,6 +1801,7 @@
 	/* put the chip in snooze mode until opened */
 	tulip_set_power_state (tp, 0, 1);
 
+	CpciRegisterDevice(pdev);
 	return 0;
 
 err_out_free_ring:
@@ -1879,6 +1880,9 @@
 #endif
 	kfree (dev);
 	pci_release_regions (pdev);
+
+	CpciUnRegisterDevice(pdev);
+
 	pci_set_drvdata (pdev, NULL);
 
 	/* pci_power_off (pdev, -1); */
diff -u -r --new-file linux/drivers/pci/Makefile ha/drivers/pci/Makefile
--- linux/drivers/pci/Makefile	Sun Sep  9 10:50:48 2001
+++ ha/drivers/pci/Makefile	Thu Dec 13 13:03:13 2001
@@ -30,6 +30,7 @@
 obj-$(CONFIG_ALL_PPC) += setup-bus.o
 obj-$(CONFIG_DDB5476) += setup-bus.o
 obj-$(CONFIG_SGI_IP27) += setup-irq.o
+obj-$(CONFIG_CPCI_HOTSWAP) += pci_auto.o
 
 ifndef CONFIG_X86
 obj-y += syscall.o
diff -u -r --new-file linux/drivers/pci/pci.c ha/drivers/pci/pci.c
--- linux/drivers/pci/pci.c	Tue Nov 20 22:53:29 2001
+++ ha/drivers/pci/pci.c	Thu Dec 13 13:03:13 2001
@@ -538,7 +538,11 @@
  *  Registration of PCI drivers and handling of hot-pluggable devices.
  */
 
+#ifdef CONFIG_CPCI_HOTSWAP
+LIST_HEAD(pci_drivers);
+#else
 static LIST_HEAD(pci_drivers);
+#endif
 
 /**
  * pci_match_device - Tell if a PCI device structure has a matching PCI device id structure
@@ -564,7 +568,7 @@
 	return NULL;
 }
 
-static int
+int
 pci_announce_device(struct pci_driver *drv, struct pci_dev *dev)
 {
 	const struct pci_device_id *id;
@@ -936,7 +940,9 @@
 						(((unsigned long) ~sz) << 32);
 #else
 			if (l) {
+#ifndef CONFIG_CPCI_HOTSWAP
 				printk(KERN_ERR "PCI: Unable to handle 64-bit address for device %s\n", dev->slot_name);
+#endif
 				res->start = 0;
 				res->flags = 0;
 				continue;
@@ -1003,7 +1009,9 @@
 		 * Ugh. We don't know enough about this bridge. Just assume
 		 * that it's entirely transparent.
 		 */
+#ifndef CONFIG_CPCI_HOTSWAP
 		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 0);
+#endif
 		child->resource[0] = child->parent->resource[0];
 	}
 
@@ -1019,7 +1027,9 @@
 		res->name = child->name;
 	} else {
 		/* See comment above. Same thing */
+#ifndef CONFIG_CPCI_HOTSWAP
 		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 1);
+#endif
 		child->resource[1] = child->parent->resource[1];
 	}
 
@@ -1038,7 +1048,9 @@
 		limit |= ((long) mem_limit_hi) << 32;
 #else
 		if (mem_base_hi || mem_limit_hi) {
+#ifndef CONFIG_CPCI_HOTSWAP
 			printk(KERN_ERR "PCI: Unable to handle 64-bit address space for %s\n", child->name);
+#endif
 			return;
 		}
 #endif
@@ -1050,7 +1062,9 @@
 		res->name = child->name;
 	} else {
 		/* See comments above */
+#ifndef CONFIG_CPCI_HOTSWAP
 		printk(KERN_ERR "Unknown bridge resource %d: assuming transparent\n", 2);
+#endif
 		child->resource[2] = child->parent->resource[2];
 	}
 }
@@ -1111,6 +1125,11 @@
  * already configured by the BIOS and after we are done with all of
  * them, we proceed to assigning numbers to the remaining buses in
  * order to avoid overlaps between old and new bus numbers.
+ *
+ * For hotswap there is a new consideration.  Due to resource limitations (namely
+ * Intel legacy hardware often has a limit of 64k for PCI IO space) the bridge
+ * may be disabled by turning off the IO, MEM and BUS MASTER bits in the command
+ * register.  In this case simple do not create entries for this bridge.
  */
 static int __devinit pci_scan_bridge(struct pci_bus *bus, struct pci_dev * dev, int max, int pass)
 {
@@ -1187,7 +1206,7 @@
  * Read interrupt line and base address registers.
  * The architecture-dependent code can tweak these, of course.
  */
-static void pci_read_irq(struct pci_dev *dev)
+void pci_read_irq(struct pci_dev *dev)
 {
 	unsigned char irq;
 
@@ -1341,6 +1360,9 @@
 	unsigned int devfn, max, pass;
 	struct list_head *ln;
 	struct pci_dev *dev, dev0;
+#ifdef CONFIG_CPCI_HOTSWAP
+	unsigned short Command;
+#endif
 
 	DBG("Scanning bus %02x\n", bus->number);
 	max = bus->secondary;
@@ -1353,6 +1375,13 @@
 	/* Go find them, Rover! */
 	for (devfn = 0; devfn < 0x100; devfn += 8) {
 		dev0.devfn = devfn;
+#ifdef CONFIG_CPCI_HOTSWAP
+			pci_read_config_word(&dev0, PCI_COMMAND, &Command);
+			if ((Command & (PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
+					PCI_COMMAND_MASTER)) == 0) {
+				continue;
+			}
+#endif
 		pci_scan_slot(&dev0);
 	}
 
diff -u -r --new-file linux/drivers/pci/pci_auto.c ha/drivers/pci/pci_auto.c
--- linux/drivers/pci/pci_auto.c	Wed Dec 31 17:00:00 1969
+++ ha/drivers/pci/pci_auto.c	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,555 @@
+/*
+ * arch/ppc/kernel/pci_auto.c
+ * 
+ * PCI autoconfiguration library
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *         Johnnie Peters <jpeters@mvista.com>
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pci.h>
+#include <linux/pci_auto.h>
+#include <linux/bootmem.h>
+
+#undef DEBUG
+#ifdef DEBUG
+#define DBG(x...) printk(x)
+#else
+#define DBG(x...)
+#endif /* DEBUG */
+
+struct pci_controller* hose_head;
+struct pci_controller** hose_tail = &hose_head;
+
+struct pci_exception exception_list[64];
+int pci_next_exception = 0;
+
+void
+pciauto_excpt_exclude_bdev(int bus, int devfn)
+{
+	exception_list[pci_next_exception].type = PCI_EXCPT_SKIP_DEV;
+	exception_list[pci_next_exception].val1 = (void *)bus;
+	exception_list[pci_next_exception].val2 = (void *)devfn;
+	pci_next_exception++;
+	return;
+}
+
+void
+pci_excpt_setup_bridge_bdev(struct pci_controller *hose, int bus, int devfn,
+			int(*func)(struct pci_controller *, int, int))
+{
+	exception_list[pci_next_exception].type = PCI_EXCPT_SETUP_BRIDGE_DEV;
+	exception_list[pci_next_exception].val1 = (void *)hose;
+	exception_list[pci_next_exception].val2 = (void *)bus;
+	exception_list[pci_next_exception].val3 = (void *)devfn;
+	exception_list[pci_next_exception].val4 = (void *)func;
+	pci_next_exception++;
+	return;
+}
+
+void
+pci_excpt_setup_device_bdev(struct pci_controller *hose, int bus, int devfn,
+			int(*func)(struct pci_controller *, int, int))
+{
+	exception_list[pci_next_exception].type = PCI_EXCPT_SETUP_DEVICE_DEV;
+	exception_list[pci_next_exception].val1 = (void *)hose;
+	exception_list[pci_next_exception].val2 = (void *)bus;
+	exception_list[pci_next_exception].val3 = (void *)devfn;
+	exception_list[pci_next_exception].val4 = (void *)func;
+	pci_next_exception++;
+	return;
+}
+
+int
+pciauto_exception_check_exclude(struct pci_controller *hose, int bus, int devfn)
+{
+	int loop;
+
+	for (loop = 0; loop < pci_next_exception; loop++) {
+		switch (exception_list[loop].type) {
+		case PCI_EXCPT_SKIP_DEV:
+			if ((bus == (int)exception_list[loop].val1) &&
+			    (devfn == (int)exception_list[loop].val2)) {
+				return PCI_EXCPT_IGNORE;
+			}
+			break;
+		case PCI_EXCPT_SETUP_BRIDGE_DEV:
+		case PCI_EXCPT_SETUP_BRIDGE_TYPE:
+			continue;
+		default:
+			continue;
+		}
+
+	}
+	return 0;
+}
+
+void *
+pciauto_exception_check_device(struct pci_controller *hose, int bus, int devfn)
+{
+	int loop;
+	int(*func)(struct pci_controller *, int, int);
+
+	for (loop = 0; loop < pci_next_exception; loop++) {
+		switch (exception_list[loop].type) {
+		case PCI_EXCPT_SETUP_DEVICE_DEV:
+			if ((hose == (struct pci_controller *)
+						exception_list[loop].val1) &&
+			    (bus == (int)exception_list[loop].val2) &&
+			    (devfn == (int)exception_list[loop].val3)) {
+				func = (int(*)(struct pci_controller *, int, int)) exception_list[loop].val4;
+				return func;
+			}
+		case PCI_EXCPT_SETUP_DEVICE_TYPE:
+			continue;
+		default:
+			continue;
+		}
+
+	}
+	return NULL;
+}
+
+void *
+pciauto_exception_check_bridge(struct pci_controller *hose, int bus, int devfn)
+{
+	int loop;
+	int(*func)(struct pci_controller *, int, int);
+
+	for (loop = 0; loop < pci_next_exception; loop++) {
+		switch (exception_list[loop].type) {
+		case PCI_EXCPT_SETUP_BRIDGE_DEV:
+			if ((hose == (struct pci_controller *)
+						exception_list[loop].val1) &&
+			    (bus == (int)exception_list[loop].val2) &&
+			    (devfn == (int)exception_list[loop].val3)) {
+				func = (int(*)(struct pci_controller *, int, int)) exception_list[loop].val4;
+				return func;
+			}
+		case PCI_EXCPT_SETUP_BRIDGE_TYPE:
+			continue;
+		default:
+			continue;
+		}
+
+	}
+	return NULL;
+}
+
+int pciauto_setup_bars(struct pci_controller *hose,
+		int current_bus,
+		int pci_devfn,
+		struct pci_auto_addrs *pci_addrs)
+{
+	unsigned int bar_response, bar_size, bar_value;
+	int bar, bar_nr = 0;
+	unsigned int addr_mask;
+	unsigned int * upper_limit;
+	unsigned int * lower_limit;
+	int found_mem64 = 0;
+
+	DBG("PCI Autoconfig: Found Bus 0x%x, Device 0x%x, Function %d\n",
+		current_bus, PCI_SLOT(pci_devfn), PCI_FUNC(pci_devfn) );
+
+	for (bar = PCI_BASE_ADDRESS_0; bar <= PCI_BASE_ADDRESS_5; bar+=4)
+	{
+		/* Tickle the BAR and get the response */
+		early_write_config_dword(hose,
+				current_bus,
+				pci_devfn,
+				bar,
+				0xffffffff);
+		early_read_config_dword(hose,
+				current_bus,
+				pci_devfn,
+				bar,
+				&bar_response);
+
+		/* If BAR is not implemented go to the next BAR */
+		if (!bar_response)
+			continue;
+
+		/* Check the BAR type and set our address mask */
+		if (bar_response & PCI_BASE_ADDRESS_SPACE)
+		{
+			addr_mask = PCI_BASE_ADDRESS_IO_MASK;
+			upper_limit = &pci_addrs->io_end;
+			lower_limit = &pci_addrs->io_start;
+			DBG("PCI Autoconfig: BAR %d, I/O, ", bar_nr);
+		}
+		else
+		{
+			if ( (bar_response & PCI_BASE_ADDRESS_MEM_TYPE_MASK) ==
+			PCI_BASE_ADDRESS_MEM_TYPE_64)
+				found_mem64 = 1;
+
+			addr_mask = PCI_BASE_ADDRESS_MEM_MASK;		
+			upper_limit = &pci_addrs->mem_end;
+			lower_limit = &pci_addrs->mem_start;
+			DBG("PCI Autoconfig: BAR %d, Mem, ", bar_nr);
+		}
+
+		/* Calculate requested size */
+		bar_size = ~(bar_response & addr_mask) + 1;
+
+		/* This is probably a hack but seems to be neccessary on
+		 * the only Intel processor based machine I have to test
+		 * on.
+		 */
+		if (bar_size < 128)
+			bar_size = 128;
+
+		/* Allocate a base address */
+		bar_value = (*upper_limit - bar_size) & ~(bar_size - 1);
+
+		if (bar_value < *lower_limit) {
+			return -1;
+		}
+
+		/* Write it out and update our limit */
+		early_write_config_dword(hose,
+				current_bus,
+				pci_devfn,
+				bar,
+				bar_value);
+
+		*upper_limit = bar_value;
+
+		/*
+		 * If we are a 64-bit decoder then increment to the
+		 * upper 32 bits of the bar and force it to locate
+		 * in the lower 4GB of memory.
+		 */ 
+		if (found_mem64)
+		{
+			bar += 4;
+			early_write_config_dword(hose,
+					current_bus,
+					pci_devfn,
+					bar,
+					0x00000000);
+		}
+
+		bar_nr++;
+
+		DBG("size=0x%x, address=0x%x\n",
+			bar_size, bar_value);
+	}
+	return 0;
+}
+
+void pciauto_prescan_setup_bridge(struct pci_controller *hose,
+		int current_bus,
+		int pci_devfn,
+		int sub_bus,
+		struct pci_auto_addrs *pci_addrs)
+{
+	unsigned short bridgestat;
+	int cmdstat;
+
+	/* Configure bus number registers */
+	early_write_config_byte(hose,
+			current_bus,
+			pci_devfn,
+			PCI_PRIMARY_BUS,
+			current_bus);
+	early_write_config_byte(hose,
+			current_bus,
+			pci_devfn,
+			PCI_SECONDARY_BUS,
+			sub_bus);
+	early_write_config_byte(hose,
+			current_bus,
+			pci_devfn,
+			PCI_SUBORDINATE_BUS,
+			0xff);
+
+	/* Round memory allocator to 1MB boundary */
+	pci_addrs->mem_end &= ~(0x100000 - 1);
+
+	/* Round I/O allocator to 4KB boundary */
+	pci_addrs->io_end &= ~(0x1000 - 1);
+
+	/* Set up memory and I/O filter limits, assume 32-bit I/O space */
+	early_write_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_MEMORY_LIMIT,
+			((pci_addrs->mem_end - 1) & 0xfff00000) >> 16);
+	early_write_config_byte(hose,
+			current_bus,
+			pci_devfn,
+			PCI_IO_LIMIT,
+			((pci_addrs->io_end - 1) & 0x0000f000) >> 8);
+	early_write_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_IO_LIMIT_UPPER16,
+			((pci_addrs->io_end - 1) & 0xffff0000) >> 16);
+			
+	/* We don't support prefetchable memory for now, so disable */
+	early_write_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_PREF_MEMORY_BASE,
+			0x1000);
+	early_write_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_PREF_MEMORY_LIMIT,
+			0x1000);
+
+	/* Disable Io and Mem space before messing with the BARs */
+	early_read_config_dword(hose,
+			current_bus,
+			pci_devfn,
+			PCI_COMMAND,
+			&cmdstat);
+	early_write_config_dword(hose,
+			current_bus,
+			pci_devfn,
+			PCI_COMMAND,
+			cmdstat &
+			~(PCI_COMMAND_IO |
+			PCI_COMMAND_MEMORY |
+			PCI_COMMAND_MASTER));
+
+	/* Disable ISA I/O port translation.  This may need to become
+	 * a configurable parameter in the future as some machines may
+	 * require this.
+	 */
+	early_read_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_BRIDGE_CONTROL,
+			&bridgestat);
+	early_write_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_BRIDGE_CONTROL,
+			bridgestat & ~PCI_BRIDGE_CTL_NO_ISA);
+}
+
+void pciauto_postscan_setup_bridge(struct pci_controller *hose,
+		int current_bus,
+		int pci_devfn,
+		int sub_bus,
+		struct pci_auto_addrs *pci_addrs)
+{
+	int cmdstat;
+
+	/* Configure bus number registers */
+	early_write_config_byte(hose,
+			current_bus,
+			pci_devfn,
+			PCI_SUBORDINATE_BUS,
+			sub_bus);
+
+	/* Round memory allocator to 1MB boundary */
+	pci_addrs->mem_end &= ~(0x100000 - 1);
+	early_write_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_MEMORY_BASE,
+			pci_addrs->mem_end >> 16);
+
+	/* Round I/O allocator to 4KB boundary */
+	pci_addrs->io_end &= ~(0x1000 - 1);
+	early_write_config_byte(hose,
+			current_bus,
+			pci_devfn,
+			PCI_IO_BASE,
+			(pci_addrs->io_end & 0x0000f000) >> 8);
+	early_write_config_word(hose,
+			current_bus,
+			pci_devfn,
+			PCI_IO_BASE_UPPER16,
+			pci_addrs->io_end >> 16);
+
+	/* Enable memory and I/O accesses, enable bus master */
+	early_read_config_dword(hose,
+			current_bus,
+			pci_devfn,
+			PCI_COMMAND,
+			&cmdstat);
+	early_write_config_dword(hose,
+			current_bus,
+			pci_devfn,
+			PCI_COMMAND,
+			cmdstat |
+			PCI_COMMAND_IO |
+			PCI_COMMAND_MEMORY |
+			PCI_COMMAND_MASTER);
+}
+
+int pciauto_bus_scan(struct pci_controller *hose, int current_bus,
+		struct pci_auto_addrs *pci_addrs)
+{
+	int sub_bus, pci_devfn, pci_class, cmdstat, found_multi=0;
+	unsigned short vid;
+	unsigned char header_type;
+	int(*func)(struct pci_controller *, int, int);
+
+	sub_bus = current_bus;
+
+	for (pci_devfn=0; pci_devfn<0xff; pci_devfn++)
+	{
+		/* Skip our host bridge */
+		if (hose && (current_bus == hose->first_busno) && (pci_devfn == 0) )
+			continue;
+
+		if (PCI_FUNC(pci_devfn) && !found_multi)
+			continue;
+
+		early_read_config_byte(hose,
+				current_bus,
+				pci_devfn,
+				PCI_HEADER_TYPE,
+				&header_type);
+
+		if (!PCI_FUNC(pci_devfn))
+			found_multi = header_type & 0x80;
+
+		early_read_config_word(hose,
+				current_bus,
+				pci_devfn,
+				PCI_VENDOR_ID,
+				&vid);
+
+		if (vid != 0xffff)
+		{
+			early_read_config_dword(hose,
+					current_bus,
+					pci_devfn,
+					PCI_CLASS_REVISION, &pci_class);
+
+			if ( (pci_class >> 16) == PCI_CLASS_BRIDGE_PCI )
+			{
+ 				DBG("PCI Autoconfig: Found P2P bridge, device %d\n", PCI_SLOT(pci_devfn));
+				if ((func = pciauto_exception_check_bridge(
+					hose, current_bus, pci_devfn))) {
+					(*func)(hose, current_bus, pci_devfn);
+					continue;
+				}
+
+				pciauto_prescan_setup_bridge(hose,
+						current_bus,
+						pci_devfn,
+						sub_bus+1,
+						pci_addrs);
+
+				if ((sub_bus = pciauto_bus_scan(hose,
+						sub_bus+1, pci_addrs)) == -1) {
+					return -1;
+				}
+
+				pciauto_postscan_setup_bridge(hose,
+						current_bus,
+						pci_devfn,
+						sub_bus,
+						pci_addrs);
+			}
+			else
+			{
+
+				if ((func = pciauto_exception_check_device(
+					hose, current_bus, pci_devfn))) {
+					(*func)(hose, current_bus, pci_devfn);
+					continue;
+				}
+
+				if ((pci_class >> 16) == PCI_CLASS_STORAGE_IDE)
+				{
+					unsigned char prg_iface;
+
+					early_read_config_byte(hose,
+							current_bus,
+							pci_devfn,
+							PCI_CLASS_PROG,
+							&prg_iface);
+					if (!(prg_iface & PCIAUTO_IDE_MODE_MASK))
+					{
+						DBG("PCI Autoconfig: Skipping legacy mode IDE controller\n");
+						continue;
+					}
+				}
+				/* Disable Io and Mem before messing with
+				 * the BARS.
+				 */
+				early_read_config_dword(hose,
+						current_bus,
+						pci_devfn,
+						PCI_COMMAND,
+						&cmdstat);
+				early_write_config_dword(hose,
+						current_bus,
+						pci_devfn,
+						PCI_COMMAND,
+						cmdstat &
+						~(PCI_COMMAND_IO |
+						PCI_COMMAND_MEMORY |
+						PCI_COMMAND_MASTER));
+
+				/* Allocate PCI I/O and/or memory space */
+				if (pciauto_setup_bars(hose,
+						current_bus,
+						pci_devfn,
+						pci_addrs)) {
+					return -1;
+				}
+
+				/*
+				 * Found a peripheral, enable some standard
+				 * settings
+				 */
+				early_read_config_dword(hose,
+						current_bus,
+						pci_devfn,
+						PCI_COMMAND,
+						&cmdstat);
+				early_write_config_dword(hose,
+						current_bus,
+						pci_devfn,
+						PCI_COMMAND,
+						cmdstat |
+						PCI_COMMAND_IO |
+						PCI_COMMAND_MEMORY |
+						PCI_COMMAND_MASTER);
+				early_write_config_byte(hose,
+						current_bus,
+						pci_devfn,
+						PCI_LATENCY_TIMER,
+						0x80);
+				early_write_config_byte(hose,
+						current_bus,
+						pci_devfn,
+						PCI_CACHE_LINE_SIZE,
+						0x0);
+			}
+		}
+	}
+	return sub_bus;
+}
+
+struct pci_controller *
+pciauto_alloc_controller(void)
+{
+        struct pci_controller *hose;
+
+        hose = (struct pci_controller *)kmalloc(sizeof(*hose), GFP_KERNEL);
+        memset(hose, 0, sizeof(struct pci_controller));
+
+        *hose_tail = hose;
+        hose_tail = &hose->next;
+
+        return hose;
+}
diff -u -r --new-file linux/drivers/pci/quirks.c ha/drivers/pci/quirks.c
--- linux/drivers/pci/quirks.c	Sun Nov 11 11:09:33 2001
+++ ha/drivers/pci/quirks.c	Thu Dec 13 13:03:13 2001
@@ -23,7 +23,7 @@
 
 /* Deal with broken BIOS'es that neglect to enable passive release,
    which can cause problems in combination with the 82441FX/PPro MTRRs */
-static void __init quirk_passive_release(struct pci_dev *dev)
+static void __devinit quirk_passive_release(struct pci_dev *dev)
 {
 	struct pci_dev *d = NULL;
 	unsigned char dlc;
@@ -50,7 +50,7 @@
 
 int isa_dma_bridge_buggy;		/* Exported */
     
-static void __init quirk_isa_dma_hangs(struct pci_dev *dev)
+static void __devinit quirk_isa_dma_hangs(struct pci_dev *dev)
 {
 	if (!isa_dma_bridge_buggy) {
 		isa_dma_bridge_buggy=1;
@@ -64,7 +64,7 @@
  *	Chipsets where PCI->PCI transfers vanish or hang
  */
 
-static void __init quirk_nopcipci(struct pci_dev *dev)
+static void __devinit quirk_nopcipci(struct pci_dev *dev)
 {
 	if((pci_pci_problems&PCIPCI_FAIL)==0)
 	{
@@ -77,7 +77,7 @@
  *	Triton requires workarounds to be used by the drivers
  */
  
-static void __init quirk_triton(struct pci_dev *dev)
+static void __devinit quirk_triton(struct pci_dev *dev)
 {
 	if((pci_pci_problems&PCIPCI_TRITON)==0)
 	{
@@ -96,7 +96,7 @@
  *	Updated based on further information from the site and also on
  *	information provided by VIA 
  */
-static void __init quirk_vialatency(struct pci_dev *dev)
+static void __devinit quirk_vialatency(struct pci_dev *dev)
 {
 	struct pci_dev *p;
 	u8 rev;
@@ -150,7 +150,7 @@
  *	VIA Apollo VP3 needs ETBF on BT848/878
  */
  
-static void __init quirk_viaetbf(struct pci_dev *dev)
+static void __devinit quirk_viaetbf(struct pci_dev *dev)
 {
 	if((pci_pci_problems&PCIPCI_VIAETBF)==0)
 	{
@@ -158,7 +158,7 @@
 		pci_pci_problems|=PCIPCI_VIAETBF;
 	}
 }
-static void __init quirk_vsfx(struct pci_dev *dev)
+static void __devinit quirk_vsfx(struct pci_dev *dev)
 {
 	if((pci_pci_problems&PCIPCI_VSFX)==0)
 	{
@@ -173,7 +173,7 @@
  *	at least
  */
  
-static void __init quirk_natoma(struct pci_dev *dev)
+static void __devinit quirk_natoma(struct pci_dev *dev)
 {
 	if((pci_pci_problems&PCIPCI_NATOMA)==0)
 	{
@@ -187,7 +187,7 @@
  *  If it's needed, re-allocate the region.
  */
 
-static void __init quirk_s3_64M(struct pci_dev *dev)
+static void __devinit quirk_s3_64M(struct pci_dev *dev)
 {
 	struct resource *r = &dev->resource[0];
 
@@ -197,7 +197,7 @@
 	}
 }
 
-static void __init quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
+static void __devinit quirk_io_region(struct pci_dev *dev, unsigned region, unsigned size, int nr)
 {
 	region &= ~(size-1);
 	if (region) {
@@ -222,7 +222,7 @@
  *	0xE0 (64 bytes of ACPI registers)
  *	0xE2 (32 bytes of SMB registers)
  */
-static void __init quirk_ali7101_acpi(struct pci_dev *dev)
+static void __devinit quirk_ali7101_acpi(struct pci_dev *dev)
 {
 	u16 region;
 
@@ -237,7 +237,7 @@
  *	0x40 (64 bytes of ACPI registers)
  *	0x90 (32 bytes of SMB registers)
  */
-static void __init quirk_piix4_acpi(struct pci_dev *dev)
+static void __devinit quirk_piix4_acpi(struct pci_dev *dev)
 {
 	u32 region;
 
@@ -251,7 +251,7 @@
  * VIA ACPI: One IO region pointed to by longword at
  *	0x48 or 0x20 (256 bytes of ACPI registers)
  */
-static void __init quirk_vt82c586_acpi(struct pci_dev *dev)
+static void __devinit quirk_vt82c586_acpi(struct pci_dev *dev)
 {
 	u8 rev;
 	u32 region;
@@ -270,7 +270,7 @@
  *	0x70 (128 bytes of hardware monitoring register)
  *	0x90 (16 bytes of SMB registers)
  */
-static void __init quirk_vt82c686_acpi(struct pci_dev *dev)
+static void __devinit quirk_vt82c686_acpi(struct pci_dev *dev)
 {
 	u16 hm;
 	u32 smb;
@@ -297,7 +297,7 @@
  * TODO: When we have device-specific interrupt routers,
  * this code will go away from quirks.
  */
-static void __init quirk_via_ioapic(struct pci_dev *dev)
+static void __devinit quirk_via_ioapic(struct pci_dev *dev)
 {
 	u8 tmp;
 	
@@ -338,7 +338,7 @@
  * value of the ACPI SCI interrupt is only done for convenience.
  *	-jgarzik
  */
-static void __init quirk_via_acpi(struct pci_dev *d)
+static void __devinit quirk_via_acpi(struct pci_dev *d)
 {
 	/*
 	 * VIA ACPI device: SCI IRQ line in PCI config byte 0x42
@@ -350,7 +350,7 @@
 		d->irq = irq;
 }
 
-static void __init quirk_via_irqpic(struct pci_dev *dev)
+static void __devinit quirk_via_irqpic(struct pci_dev *dev)
 {
 	u8 irq, new_irq = dev->irq & 0xf;
 
@@ -377,7 +377,7 @@
  *
  * We mask out all r/wc bits, too.
  */
-static void __init quirk_piix3_usb(struct pci_dev *dev)
+static void __devinit quirk_piix3_usb(struct pci_dev *dev)
 {
 	u16 legsup;
 
@@ -392,7 +392,7 @@
  * We need to switch it off to be able to recognize the real
  * type of the chip.
  */
-static void __init quirk_vt82c598_id(struct pci_dev *dev)
+static void __devinit quirk_vt82c598_id(struct pci_dev *dev)
 {
 	pci_write_config_byte(dev, 0xfc, 0);
 	pci_read_config_word(dev, PCI_DEVICE_ID, &dev->device);
@@ -404,7 +404,7 @@
  * do this even if the Linux CardBus driver is not loaded, because
  * the Linux i82365 driver does not (and should not) handle CardBus.
  */
-static void __init quirk_cardbus_legacy(struct pci_dev *dev)
+static void __devinit quirk_cardbus_legacy(struct pci_dev *dev)
 {
 	if ((PCI_CLASS_BRIDGE_CARDBUS << 8) ^ dev->class)
 		return;
@@ -421,7 +421,7 @@
  * of course. However the advice is demonstrably good even if so..
  */
  
-static void __init quirk_amd_ioapic(struct pci_dev *dev)
+static void __devinit quirk_amd_ioapic(struct pci_dev *dev)
 {
 	u8 rev;
 
@@ -441,7 +441,7 @@
  * who turn it off!
  */
  
-static void __init quirk_amd_ordering(struct pci_dev *dev)
+static void __devinit quirk_amd_ordering(struct pci_dev *dev)
 {
 	u32 pcic;
 	
@@ -458,7 +458,7 @@
  *  The main table of quirks.
  */
 
-static struct pci_fixup pci_fixups[] __initdata = {
+static struct pci_fixup pci_fixups[] __devinitdata = {
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release },
 	{ PCI_FIXUP_FINAL,	PCI_VENDOR_ID_INTEL,	PCI_DEVICE_ID_INTEL_82441,	quirk_passive_release },
 	/*
diff -u -r --new-file linux/include/asm-i386/pci-bridge.h ha/include/asm-i386/pci-bridge.h
--- linux/include/asm-i386/pci-bridge.h	Wed Dec 31 17:00:00 1969
+++ ha/include/asm-i386/pci-bridge.h	Thu Dec 13 13:25:22 2001
@@ -0,0 +1,67 @@
+/*
+ */
+#ifdef __KERNEL__
+#ifndef _ASM_PCI_BRIDGE_H
+#define _ASM_PCI_BRIDGE_H
+
+#include <linux/ioport.h>
+#include <linux/pci.h>
+
+struct device_node;
+struct pci_controller;
+
+/*
+ * Structure of a PCI controller (host bridge)
+ */
+struct pci_controller {
+	int index;			/* used for pci_controller_num */
+	struct pci_controller *next;
+        struct pci_bus *bus;
+	void *arch_data;
+
+	int first_busno;
+	int last_busno;
+	int bus_offset;
+        
+	void *io_base_virt;
+	unsigned long io_base_phys;
+	
+	/* Some machines (PReP) have a non 1:1 mapping of
+	 * the PCI memory space in the CPU bus space
+	 */
+	unsigned long pci_mem_offset;
+
+	struct pci_ops *ops;
+	volatile unsigned int *cfg_addr;
+	volatile unsigned char *cfg_data;
+
+	/* Currently, we limit ourselves to 1 IO range and 3 mem
+	 * ranges since the common pci_bus structure can't handle more
+	 */
+	struct resource	io_resource;
+	struct resource mem_resources[3];
+	int mem_resource_count;
+
+	/* Host bridge I/O and Memory space
+	 * Used for BAR placement algorithms
+	 */
+	struct resource io_space;
+	struct resource mem_space;
+};
+
+/* These are used for config access before all the PCI probing
+   has been done. */
+int early_read_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+			   int where, u8 *val);
+int early_read_config_word(struct pci_controller *hose, int bus, int dev_fn,
+			   int where, u16 *val);
+int early_read_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u32 *val);
+int early_write_config_byte(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u8 val);
+int early_write_config_word(struct pci_controller *hose, int bus, int dev_fn,
+			    int where, u16 val);
+int early_write_config_dword(struct pci_controller *hose, int bus, int dev_fn,
+			     int where, u32 val);
+#endif
+#endif /* __KERNEL__ */
diff -u -r --new-file linux/include/linux/cpci.h ha/include/linux/cpci.h
--- linux/include/linux/cpci.h	Wed Dec 31 17:00:00 1969
+++ ha/include/linux/cpci.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,110 @@
+/*
+ * cpci.h
+ *
+ * Common access routines for cPCI interface.
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef CPCI_H
+#define CPCI_H
+
+/* Events currently defined. */
+#define CPCI_EVENT_INSERT	1
+#define CPCI_EVENT_REMOVE	2
+#define CPCI_EVENT_AVAIL	3
+#define CPCI_EVENT_SHUTDOWN	4
+#define CPCI_EVENT_CLOSED	5
+
+#define CPCI_BOARD_INS_SUCC	6
+#define CPCI_BOARD_INS_FAIL	7
+#define   CPCI_BI_FAIL_BUSY	  1	/* Slot already alloced */
+#define   CPCI_BI_FAIL_HEALTH	  2	/* Healthy not set */
+#define   CPCI_BI_FAIL_CONFIG	  3	/* PCI bus config failed */
+#define   CPCI_BI_FAIL_NODEV	  4	/* No device found in slot. */
+#define   CPCI_BI_FAIL_NOSUB	  5	/* No subordinate device fount */
+#define   CPCI_BI_FAIL_SCAN	  6	/* PCI bus scan failed */
+#define CPCI_BOARD_REM_SUCC	8
+#define CPCI_BOARD_REM_FAIL	9
+
+/* cPCI chassis types currently known. */
+#define CPCI_CHASSIS_UNKNOWN       0x0
+#define CPCI_CHASSIS_GEN_HOTSWAP   0x10001
+#define CPCI_CHASSIS_MOT_CPX8216   0x20002
+#define CPCI_CHASSIS_MOT_CPX8216A  0x20003
+#define CPCI_CHASSIS_MOT_CPX8216T  0x20004
+#define CPCI_CHASSIS_MOT_CPX8221   0x30005
+#define CPCI_CHASSIS_ZIA_5083      0x20006
+
+/* Board allocate status codes. */
+#define CPCI_SLOT_FREE          0	/* Slot empty */
+#define CPCI_SLOT_ALLOCATED     1	/* Slot Allocated */
+#define CPCI_SLOT_INSFAILED     2	/* Slot insert failed with reasin below. */
+
+#define MAX_SLOT_NUM	7	/* PCI bus cannot be bigger than this on any one segment. */
+
+typedef struct _CpciIoctlBusInfo {
+	int Bus;
+	int StartSlot;
+	int EndSlot;
+	int Allocated[MAX_SLOT_NUM];
+} CpciIoctlBusInfo;
+
+#define CPCI_MAX_NAME_LEN	16
+#define CPCI_MAX_SLOT_INFO	32
+
+#define CPCI_DRIVER_NEEDED	0
+#define CPCI_DRIVER_INSTALLED	1
+
+typedef struct _CpciIoctlDevInfo {
+	int Vendor;
+	int Device;
+	int SubSystemVendor;
+	int SubSystemDevice;
+	int Class;
+	int DriverStatus;
+	char Name[CPCI_MAX_NAME_LEN];
+} CpciIoctlDevInfo;
+
+typedef struct _CpciIoctlSlotInfo {
+	int Domain;
+	int Slot;
+	int NumSubDevs;
+	CpciIoctlDevInfo DevInfo[CPCI_MAX_SLOT_INFO];
+} CpciIoctlSlotInfo;
+
+/* cPCI ioctl calls currently available */
+#define CPCI_MAGIC 0xc0
+
+#define CPCI_ADD_BUS		_IOW(CPCI_MAGIC, 1, int)
+#define CPCI_DEL_BUS		_IOW(CPCI_MAGIC, 2, int)
+#define CPCI_ADD_SLOT		_IOW(CPCI_MAGIC, 3, int)
+#define CPCI_DEL_SLOT		_IOW(CPCI_MAGIC, 4, int)
+#define CPCI_GET_CHASSIS_TYPE	_IOR(CPCI_MAGIC, 5, int)
+#define CPCI_GET_BUS_INFO	_IOWR(CPCI_MAGIC, 6, CpciIoctlBusInfo)
+#define CPCI_GET_SLOT_INFO	_IOWR(CPCI_MAGIC, 7, CpciIoctlSlotInfo)
+
+#endif /* CPCI_H */
diff -u -r --new-file linux/include/linux/event.h ha/include/linux/event.h
--- linux/include/linux/event.h	Wed Dec 31 17:00:00 1969
+++ ha/include/linux/event.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,114 @@
+/*
+ * event.h
+ *
+ * Kernel event access routines and data structures.
+ *
+ * Author: MontaVista Software, Inc.
+ *         source@mvista.com
+ *
+ * Copyright 2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ *  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ *  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ *  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ *  OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ *  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ *  TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
+ *  USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef EVENT_H
+#define EVENT_H
+
+/* User request uses for the Flag in EventPacket */
+#define EF_WAIT_FOR_EVENT	0x1
+
+/* Flag values to indicate the status of the extra data field. */
+#define EF_DATA_AVAIL		0x2
+#define EF_DATA_FAILURE		0x4
+
+/* Structure of an event packet. */
+typedef struct event_packet {
+	int Flag;		/* Used to indicate sleep wait or not. */
+	int Id;
+	int Pri;
+	int Class;
+	int Event;
+	struct timeval TimeStamp;
+	int Info[4];
+	int DataLen;
+	void *Data;
+	struct event_packet *Next;
+} EventPacket;
+
+/* Structure used to request and event to be sent to a process or not. */
+typedef struct event_req_info {
+	int Id;
+	int Pri;
+	int Class;
+	int Event;
+} EventReq;
+
+/* Data structure used by EVENT_REG_ID, EVENT_UNREG_ID and EVENT_GET_ID. */
+typedef struct event_id {
+	int Id;
+	char IdString[16];
+} EventIdPacket;
+
+/* User level ioctl cmd identifiers. */
+#define EVENT_MAGIC 0xd0
+
+#define EVENT_REG_ID			_IOWR(EVENT_MAGIC, 1, EventIdPacket)
+#define EVENT_UNREG_ID			_IOW(EVENT_MAGIC, 2, EventIdPacket)
+#define EVENT_GET_ID			_IOWR(EVENT_MAGIC, 3, EventIdPacket)
+#define EVENT_GET_ID_STRING		_IOWR(EVENT_MAGIC, 4, EventIdPacket)
+
+#define EVENT_REG_EVENT_CLASS		_IOWR(EVENT_MAGIC, 5, EventIdPacket)
+#define EVENT_UNREG_EVENT_CLASS		_IOW(EVENT_MAGIC, 6, EventIdPacket)
+#define EVENT_GET_EVENT_CLASS		_IOWR(EVENT_MAGIC, 7, EventIdPacket)
+#define EVENT_GET_EVENT_CLASS_STRING	_IOWR(EVENT_MAGIC, 8, EventIdPacket)
+
+#define EVENT_SUBSCRIBE_EVENT_BY_TYPE	_IOW(EVENT_MAGIC, 9, EventReq)
+#define EVENT_UNSUBSCRIBE_EVENT_BY_TYPE	_IOW(EVENT_MAGIC, 10, EventReq)
+#define EVENT_SUBSCRIBE_EVENT_BY_CLASS	_IOW(EVENT_MAGIC, 11, int)
+#define EVENT_UNSUBSCRIBE_EVENT_BY_CLASS _IOW(EVENT_MAGIC, 12, int)
+
+#define EVENT_GET_EVENT			_IOWR(EVENT_MAGIC, 13, EventPacket)
+#define EVENT_SEND_EVENT		_IOW(EVENT_MAGIC, 14, EventPacket)
+
+/* Kernel interface access function prototypes. */
+int  EventRegisterId(char *);
+int  EventUnRegisterId(int);
+int  EventGetId(char *);
+int  EventGetIdString(int, char *);
+
+int  EventRegisterEventClass(char *, int *);
+int  EventUnRegisterEventClass(int);
+int  EventGetEventClass(char *);
+int  EventGetEventClassString(int, char *);
+
+int  EventSubscribeEventByType(int, int, int, int,
+		int (*)(int, int, int, int, int, int, int, int, int, void *));
+int  EventUnSubscribeEventByType(int, int, int);
+int  EventSubscribeEventByClass(int, int, int,
+		int (*)(int, int, int, int, int, int, int, int, int, void *));
+int  EventUnSubscribeEventByClass(int, int);
+
+int EventGetEvent(int, int, EventPacket *);
+void EventFree(EventPacket *, int);
+
+int  EventSendEvent(int, int, int, int, int, int, int, int, int, void *);
+
+#endif /* EVENT_H */
diff -u -r --new-file linux/include/linux/init.h ha/include/linux/init.h
--- linux/include/linux/init.h	Thu Nov 22 12:46:18 2001
+++ ha/include/linux/init.h	Thu Dec 13 13:23:46 2001
@@ -143,7 +143,7 @@
 
 #endif
 
-#ifdef CONFIG_HOTPLUG
+#if defined(CONFIG_HOTPLUG) || defined(CONFIG_CPCI_HOTSWAP)
 #define __devinit
 #define __devinitdata
 #define __devexit
diff -u -r --new-file linux/include/linux/mot82XXhsc.h ha/include/linux/mot82XXhsc.h
--- linux/include/linux/mot82XXhsc.h	Wed Dec 31 17:00:00 1969
+++ ha/include/linux/mot82XXhsc.h	Thu Dec 13 13:03:13 2001
@@ -0,0 +1,277 @@
+/*
+ * mot82XXhsc.h
+ *
+ * Motorola 82XX hot swap controller driver.
+ *
+ * Author: MontaVista Software, Inc.
+ *         jpeters@mvista.com
+ *         source@mvista.com
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ *  This program is free software; you can redistribute it and/or modify it
+ *  under the terms of the GNU General Public License as published by the
+ *  Free Software Foundation; either version 2 of the License, or (at your
+ *  option) any later version.
+ *
+ *  THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ *  INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 
+ *  AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL 
+ *  THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ *  EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ *  PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  You should have received a copy of the GNU General Public License along
+ *  with this program; if not, write to the Free Software Foundation, Inc.,
+ *  675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef MOT82XXHSC_H
+#define MOT82XXHSC_H
+
+/* How many of each exists. */
+#define MOTHSC_NUM_SLOTS	16	/* number of card slots */
+#define MOTHSC_NUM_PS		3	/* number of power supplies */
+#define MOTHSC_NUM_PBAY		4	/* number of peripherl bays */
+#define MOTHSC_NUM_INTSTAT	3	/* number of interrupt status regs */
+#define MOTHSC_NUM_BUS		2	/* number of buses. */
+
+/* Data structure of events to be returned. */
+typedef struct mot82XXEvent {
+	int	Event;		/* Event happinging. */
+	int	Unit;		/* Particular device. */
+	int	Val;		/* More info - normally on or off */
+} MotHscEvent;
+
+/* Max number of events to return at one time. */
+#define MOTHSC_EVENTS_MAX	16
+
+/* Ioctl data structure for events. */
+typedef struct mot82XXEvents {
+	int		Count;
+	MotHscEvent 	Events[MOTHSC_EVENTS_MAX];
+} MotHscEvents;
+
+/* specification for enableing or disableing events. */
+#define MOT82XXHSC_EVENT_ON	1
+#define MOT82XXHSC_EVENT_OFF	0
+
+/* Known event types. */
+#define MOT82XXHSC_EVENT_ALARM		1
+
+#define MOT82XXHSC_EVENT_LED		2
+
+#define MOT82XXHSC_EVENT_PBAY1		3
+#define MOT82XXHSC_EVENT_PBAY2		4
+#define MOT82XXHSC_EVENT_PBAY3		5
+#define MOT82XXHSC_EVENT_PBAY4		6
+
+#define MOT82XXHSC_EVENT_PS1		7
+#define MOT82XXHSC_EVENT_PS2		8
+#define MOT82XXHSC_EVENT_PS3		9
+
+#define MOT82XXHSC_EVENT_BUS_UNKNOWN	10
+#define MOT82XXHSC_EVENT_BUS_TAKE_REQ	11
+#define MOT82XXHSC_EVENT_BUS_TAKE_DONE	12
+#define MOT82XXHSC_EVENT_BUS_RELEASED	13
+#define MOT82XXHSC_EVENT_BUS_ALLOW	14
+#define MOT82XXHSC_EVENT_BUS_DISALLOW	15
+
+#define MOT82XXHSC_EVENT_SLOT1		16
+#define MOT82XXHSC_EVENT_SLOT2		17
+#define MOT82XXHSC_EVENT_SLOT3		18
+#define MOT82XXHSC_EVENT_SLOT4		19
+#define MOT82XXHSC_EVENT_SLOT5		20
+#define MOT82XXHSC_EVENT_SLOT6		21
+#define MOT82XXHSC_EVENT_HOSTA		22
+#define MOT82XXHSC_EVENT_HSCA		23
+#define MOT82XXHSC_EVENT_HOSTB		24
+#define MOT82XXHSC_EVENT_HSCB		25
+#define MOT82XXHSC_EVENT_SLOT11		26
+#define MOT82XXHSC_EVENT_SLOT12		27
+#define MOT82XXHSC_EVENT_SLOT13		28
+#define MOT82XXHSC_EVENT_SLOT14		29
+#define MOT82XXHSC_EVENT_SLOT15		30
+#define MOT82XXHSC_EVENT_SLOT16		31
+
+#define MOT82XXHSC_EVENT_ENUM		32
+#define MOT82XXHSC_EVENT_ENUMMASK	33
+
+/* Structure used to return current register setting.  For debug onlty. */
+typedef struct mot82XXRegisters {
+	unsigned int	MhrSlot[MOTHSC_NUM_SLOTS];
+	unsigned int	MhrPower[MOTHSC_NUM_PS];
+	unsigned int	MhrPBay[MOTHSC_NUM_PBAY];
+	unsigned int	MhrIntStatMask;
+	unsigned int	MhrIntStatus[MOTHSC_NUM_INTSTAT];
+	unsigned int	MhrBusControl[MOTHSC_NUM_BUS];
+	unsigned int	MhrEEprom;
+	unsigned int	MhrSysLed;
+	unsigned int	MhrAlarm;
+	unsigned int	MhrIntMask;
+} MotHscRegisters;
+
+/* Specify the particular bit should be set or cleared. */
+#define MOT82XXHSC_SET	        1
+#define MOT82XXHSC_CLEAR	0
+
+/* Data structure for alarm control ioctl and the bits to be used. */
+typedef struct mot82XXAlarmLedSet {
+	int		MasFlag;
+	unsigned int	MasBits;
+} MotHscAlarmLedSet;
+
+#define MOT82XXHSC_ALARM_CRITICAL 0x1
+#define MOT82XXHSC_ALARM_MAJOR	  0x2
+#define MOT82XXHSC_ALARM_MINOR	  0x4
+#define MOT82XXHSC_ALARM_RACK	  0x8
+#define MOT82XXHSC_ALARM_MASK	  0xf
+
+/* Bits for chassis LED controls.  Alarm data structure used. */
+#define MOT82XXHSC_LED1		  0x1
+#define MOT82XXHSC_LED2		  0x2
+#define MOT82XXHSC_LED3		  0x4
+#define MOT82XXHSC_LED4		  0x8
+#define MOT82XXHSC_LED_MASK	  0xf
+
+/* Structure und bits sed for peripheal bay controls. */
+typedef struct mot82XXPBayInfo {
+	int		MpbiFlag;
+	int		MpbiBay;
+	unsigned int	MpbiBits;
+} MotHscPBayInfo;
+
+#define MOT82XXHSC_PBAY_PRESENT	  0x1
+#define MOT82XXHSC_PBAY_POWER	  0x2
+#define MOT82XXHSC_PBAY_OWNDEVICE 0x4
+#define MOT82XXHSC_PBAY_LED1	  0x8
+#define MOT82XXHSC_PBAY_LED2	  0x10
+#define MOT82XXHSC_PBAY_MASK	  0x1f
+
+/* Structure und bits sed for power supply controls. */
+typedef struct mot82XXPsInfo {
+	int		MpsiFlag;
+	int		MpsiPS;
+	unsigned int	MpsiBits;
+} MotHscPsInfo;
+
+#define MOT82XXHSC_PS_PRESENT	  0x1
+#define MOT82XXHSC_PS_POWER	  0x2
+#define MOT82XXHSC_PS_TOLERANCE	  0x4
+#define MOT82XXHSC_PS_COOL_ALARM  0x8
+#define MOT82XXHSC_PS_COOL_FAIL	  0x10
+#define MOT82XXHSC_PS_LED1	  0x20
+#define MOT82XXHSC_PS_LED2	  0x40
+#define MOT82XXHSC_PS_FAN_LED1	  0x80
+#define MOT82XXHSC_PS_FAN_LED2	  0x100
+#define MOT82XXHSC_PS_FAN_PRESENT 0x200
+#define MOT82XXHSC_PS_FAN_SPEED	  0x400
+#define MOT82XXHSC_PS_FAN_FAIL	  0x800
+#define MOT82XXHSC_PS_MASK	  0xfff
+
+/* Bit fields used for bus control. */
+#define MOT82XXHSC_DOMAIN_A	  0x1
+#define MOT82XXHSC_DOMAIN_B	  0x2
+
+#define MOT82XXHSC_BUS_TIMEO_MASK 0xffff0000
+#define MOT82XXHSC_BUS_A	  0x1
+#define MOT82XXHSC_BUS_B	  0x2
+#define MOT82XXHSC_BUS_MASK	  0x3
+#define MOT82XXHSC_BUS_RELEASE	  0x4
+#define MOT82XXHSC_BUS_MODEMASK	  0xc
+#define MOT82XXHSC_BUS_ALLOWTO	  0x10000
+
+#define MOT82XXHSC_BUS_FREE	  1
+#define MOT82XXHSC_BUS_OTHER	  2
+#define MOT82XXHSC_BUS_REQUESTED  3
+#define MOT82XXHSC_BUS_TRAN_START 4
+#define MOT82XXHSC_BUS_STOPED	  5
+#define MOT82XXHSC_BUS_TRAN_ACK	  6
+#define MOT82XXHSC_BUS_ENABLE	  7
+#define MOT82XXHSC_BUS_TRAN_DONE  8
+#define MOT82XXHSC_BUS_MINE	  9
+
+/* Date structure used to secify controls for slot registers. */
+typedef struct mot82XXSlotInfo {
+	int		MsiFlag;
+	int		MsiSlot;
+	unsigned int	MsiBits;
+} MotHscSlotInfo;
+
+/* Bits for slot control.  Most of these are the same whether they
+ * are host, non host or hsc slots. */
+#define MOT82XXHSC_SLOT_PRESENT	  0x1
+#define MOT82XXHSC_SLOT_POWER	  0x2
+#define MOT82XXHSC_SLOT_IGN_HLTH  0x4
+#define MOT82XXHSC_SLOT_RESET	  0x8
+#define MOT82XXHSC_SLOT_CONNECT	  0x10
+#define MOT82XXHSC_SLOT_CONNED	  0x20
+#define MOT82XXHSC_SLOT_HEALTHY	  0x40
+#define MOT82XXHSC_SLOT_LED1	  0x80
+#define MOT82XXHSC_SLOT_LED2	  0x100
+#define MOT82XXHSC_SLOT_LED3	  0x200
+#define MOT82XXHSC_SLOT_ACTIVE	  0x400
+
+/* The bridge slots have a few different bit defines. */
+#define MOT82XXHSC_HSC_INSERT	  0x2
+#define MOT82XXHSC_HSC_REMOVE	  0x4
+#define MOT82XXHSC_HSC_INSTALL	  0x8
+#define MOT82XXHSC_HSC_EJECTOR	  0x10
+
+/* Bit bask of setable fits for slot registers. */
+#define MOT82XXHSC_NH_MASK	  0x396	/*Only valid setable bits */
+#define MOT82XXHSC_HOST_MASK	  0x382
+#define MOT82XXHSC_HSC_MASK	  0x386
+
+/* Specify the correct arguments for variois slot control functions. */
+#define MOT82XXHSC_SLOT1	  1
+#define MOT82XXHSC_SLOT2	  2
+#define MOT82XXHSC_SLOT3	  3
+#define MOT82XXHSC_SLOT4	  4
+#define MOT82XXHSC_SLOT5	  5
+#define MOT82XXHSC_SLOT6	  6
+#define MOT82XXHSC_SLOT11	  11
+#define MOT82XXHSC_SLOT12	  12
+#define MOT82XXHSC_SLOT13	  13
+#define MOT82XXHSC_SLOT14	  14
+#define MOT82XXHSC_SLOT15	  15
+#define MOT82XXHSC_SLOT16	  16
+
+#define MOT82XXHSC_HOSTA	  1
+#define MOT82XXHSC_HOSTB	  2
+
+#define MOT82XXHSC_HSCA		  1
+#define MOT82XXHSC_HSCB		  2
+
+/* Ioctl command identifiers. */
+#define MOT82XXHSC_MAGIC	0xb0
+#define HSC_GET_REGISTERS	_IOR(MOT82XXHSC_MAGIC, 1, MotHscRegisters)
+#define HSC_GET_EVENTS		_IOR(MOT82XXHSC_MAGIC, 2, MotHscEvents)
+#define HSC_SET_ALARM		_IOW(MOT82XXHSC_MAGIC, 3, MotHscAlarmLedSet)
+#define HSC_GET_ALARM_STAT	_IOR(MOT82XXHSC_MAGIC, 4, int)
+#define HSC_SET_LED		_IOW(MOT82XXHSC_MAGIC, 5, MotHscAlarmLedSet)
+#define HSC_GET_LED_STAT	_IOR(MOT82XXHSC_MAGIC, 6, int)
+#define HSC_SET_PBAY		_IOW(MOT82XXHSC_MAGIC, 7, MotHscPBayInfo)
+#define HSC_GET_PBAY_STAT	_IOWR(MOT82XXHSC_MAGIC, 8, int)
+#define HSC_SET_POWER		_IOW(MOT82XXHSC_MAGIC, 9, MotHscPsInfo)
+#define HSC_GET_POWER_STAT	_IOWR(MOT82XXHSC_MAGIC, 10, int)
+#define HSC_GET_LOCALHOST	_IOR(MOT82XXHSC_MAGIC, 11, int)
+#define HSC_GET_BUS_STATE	_IOWR(MOT82XXHSC_MAGIC, 12, int)
+#define HSC_TAKE_BUS		_IOW(MOT82XXHSC_MAGIC, 13, int)
+#define HSC_FREE_BUS		_IOW(MOT82XXHSC_MAGIC, 14, int)
+#define HSC_ALLOW_BUS_TAKE	_IOW(MOT82XXHSC_MAGIC, 15, int)
+#define HSC_SET_ENUMMASK	_IOW(MOT82XXHSC_MAGIC, 16, int)
+#define HSC_GET_ENUMMASK	_IOR(MOT82XXHSC_MAGIC, 17, int)
+#define HSC_GET_ENUM		_IOR(MOT82XXHSC_MAGIC, 18, int)
+#define HSC_GET_NONHOST		_IOWR(MOT82XXHSC_MAGIC, 19, int)
+#define HSC_SET_NONHOST		_IOW(MOT82XXHSC_MAGIC, 20, MotHscSlotInfo)
+#define HSC_GET_HOST		_IOWR(MOT82XXHSC_MAGIC, 21, int)
+#define HSC_SET_HOST		_IOW(MOT82XXHSC_MAGIC, 22, MotHscSlotInfo)
+#define HSC_GET_HSC		_IOWR(MOT82XXHSC_MAGIC, 23, int)
+#define HSC_SET_HSC		_IOW(MOT82XXHSC_MAGIC, 24, MotHscSlotInfo)
+
+#endif /* MOT82XXHSC_H */
diff -u -r --new-file linux/include/linux/pci.h ha/include/linux/pci.h
--- linux/include/linux/pci.h	Thu Nov 22 12:46:30 2001
+++ ha/include/linux/pci.h	Thu Dec 13 13:25:12 2001
@@ -381,7 +381,9 @@
 	int		active;		/* ISAPnP: device is active */
 	int		ro;		/* ISAPnP: read only */
 	unsigned short	regs;		/* ISAPnP: supported registers */
-
+#ifdef CONFIG_CPCI_HOTSWAP
+	int		cpci_location;	/* cPCI slot this device is in */
+#endif
 	int (*prepare)(struct pci_dev *dev);	/* ISAPnP hooks */
 	int (*activate)(struct pci_dev *dev);
 	int (*deactivate)(struct pci_dev *dev);
@@ -595,6 +597,11 @@
 unsigned int pci_do_scan_bus(struct pci_bus *bus);
 struct pci_bus * pci_add_new_bus(struct pci_bus *parent, struct pci_dev *dev, int busnr);
 
+/* Additional functions exported for use by the cPCI Hotswap routines */
+struct pci_dev *pci_scan_device(struct pci_dev *);
+void pci_read_bridge_bases(struct pci_bus *);
+int pci_announce_device(struct pci_driver *, struct pci_dev *);
+
 /* kmem_cache style wrapper around pci_alloc_consistent() */
 struct pci_pool *pci_pool_create (const char *name, struct pci_dev *dev,
 		size_t size, size_t align, size_t allocation, int flags);
@@ -691,6 +698,10 @@
 	if (rc == 0)
 		rc = -ENODEV;		
 #endif
+#ifdef CONFIG_CPCI_HOTSWAP
+	if (rc == 0)
+		return 0;
+#endif
 
 	/* if we get here, we need to clean up pci driver instance
 	 * and return some sort of error */
@@ -755,5 +766,13 @@
 #define PCIPCI_VIAETBF		8
 #define PCIPCI_VSFX		16
 
+#ifdef CONFIG_CPCI_HOTSWAP
+void CpciRegisterDevice(struct pci_dev *);
+void CpciUnRegisterDevice(struct pci_dev *);
+#else
+#define CpciRegisterDevice(x);
+#define CpciUnRegisterDevice(x);
+
+#endif /* CONFIG_CPCI_HOTSWAP */
 #endif /* __KERNEL__ */
 #endif /* LINUX_PCI_H */
diff -u -r --new-file linux/include/linux/pci_auto.h ha/include/linux/pci_auto.h
--- linux/include/linux/pci_auto.h	Wed Dec 31 17:00:00 1969
+++ ha/include/linux/pci_auto.h	Thu Dec 13 13:25:22 2001
@@ -0,0 +1,64 @@
+/*
+ * include/linux/pci_auto.h
+ * 
+ * PCI autoconfiguration library definitions
+ *
+ * Author: Matt Porter <mporter@mvista.com>
+ *         Johnnie Peters <jpeters@mvista.com)
+ *
+ * Copyright 2000,2001 MontaVista Software Inc.
+ *
+ * This program is free software; you can redistribute  it and/or modify it
+ * under  the terms of  the GNU General  Public License as published by the
+ * Free Software Foundation;  either version 2 of the  License, or (at your
+ * option) any later version.
+ */
+
+#ifndef _PCI_AUTO_H
+#define _PCI_AUTO_H
+
+#include <asm/pci-bridge.h>
+
+struct pci_exception {
+	int type;
+	void *val1;
+	void *val2;
+	void *val3;
+	void *val4;
+};
+
+#define PCI_EXCPT_SKIP_DEV		1  /* skip bus, devfn */
+#define PCI_EXCPT_SETUP_BRIDGE_DEV	2  /* setup bus, devfn */
+#define PCI_EXCPT_SETUP_BRIDGE_TYPE	3  /* setup vendor, device */
+#define PCI_EXCPT_SETUP_DEVICE_DEV	4  /* setup bus, devfn */
+#define PCI_EXCPT_SETUP_DEVICE_TYPE	5  /* setup vendor, device */
+
+#define PCI_EXCPT_IGNORE		1
+#define PCI_EXCPT_DONT_SCAN		2
+
+struct pci_auto_addrs {
+	unsigned int io_start;
+	unsigned int io_end;
+	unsigned int mem_start;
+	unsigned int mem_end;
+};
+
+void	pciauto_excpt_exclude_bdev(int, int);
+void	pci_excpt_setup_bridge_bdev(struct pci_controller *, int, int,
+				int(*)(struct pci_controller *, int, int));
+void	pci_excpt_setup_device_bdev(struct pci_controller *, int, int,
+				int(*)(struct pci_controller *, int, int));
+
+int	pciauto_setup_bars(struct pci_controller *, int, int,
+					struct pci_auto_addrs *);
+void	pciauto_prescan_setup_bridge(struct pci_controller *, int, int, int,
+					struct pci_auto_addrs *);
+void	pciauto_postscan_setup_bridge(struct pci_controller *, int, int, int,
+					struct pci_auto_addrs *);
+int	pciauto_bus_scan(struct pci_controller *, int,
+					struct pci_auto_addrs *);
+struct pci_controller *pciauto_alloc_controller(void);
+
+#define	PCIAUTO_IDE_MODE_MASK		0x05
+
+#endif /* __PCI_AUTO_H */
diff -u -r --new-file linux/include/linux/pci_ids.h ha/include/linux/pci_ids.h
--- linux/include/linux/pci_ids.h	Fri Nov  9 15:11:15 2001
+++ ha/include/linux/pci_ids.h	Thu Dec 13 13:03:13 2001
@@ -314,6 +314,7 @@
 #define PCI_DEVICE_ID_DEC_21152		0x0024
 #define PCI_DEVICE_ID_DEC_21153		0x0025
 #define PCI_DEVICE_ID_DEC_21154		0x0026
+#define PCI_DEVICE_ID_DEC_21554		0x0046
 #define PCI_DEVICE_ID_DEC_21285		0x1065
 #define PCI_DEVICE_ID_COMPAQ_42XX	0x0046
 
@@ -595,6 +596,9 @@
 #define PCI_DEVICE_ID_MOTOROLA_RAVEN	0x4801
 #define PCI_DEVICE_ID_MOTOROLA_FALCON	0x4802
 #define PCI_DEVICE_ID_MOTOROLA_CPX8216	0x4806
+#define PCI_DEVICE_ID_MOTOROLA_CPX8221	0x4807
+#define PCI_DEVICE_ID_MOTOROLA_CPX8216T	0x4809
+#define PCI_DEVICE_ID_MOTOROLA_CPX8216A	0x480a
 
 #define PCI_VENDOR_ID_PROMISE		0x105a
 #define PCI_DEVICE_ID_PROMISE_20265	0x0d30
diff -u -r --new-file linux/init/main.c ha/init/main.c
--- linux/init/main.c	Fri Nov  9 15:15:00 2001
+++ ha/init/main.c	Thu Dec 13 13:15:25 2001
@@ -107,6 +107,13 @@
 extern void ipc_init(void);
 #endif
 
+#ifdef CONFIG_EVENT_BROKER
+extern int event_init(void);
+#endif
+#ifdef CONFIG_CPCI_HOTSWAP
+extern int cpci_init(void);
+#endif
+
 /*
  * Boot command-line arguments
  */
@@ -700,6 +707,12 @@
 #endif
 #if defined(CONFIG_PPC)
 	ppc_init();
+#endif
+#ifdef CONFIG_EVENT_BROKER
+	event_init();
+#endif
+#ifdef CONFIG_CPCI_HOTSWAP
+	cpci_init();
 #endif
 #ifdef CONFIG_MCA
 	mca_init();
+
