*/
 #define EEH_MAX_FAILS  100000
 
+/* Misc forward declaraions */
+static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn);
+
 /* RTAS tokens */
 static int ibm_set_eeh_option;
 static int ibm_set_slot_reset;
  */
 void __init pci_addr_cache_build(void)
 {
+       struct device_node *dn;
        struct pci_dev *dev = NULL;
 
        if (!eeh_subsystem_enabled)
                        continue;
                }
                pci_addr_cache_insert_device(dev);
+
+               /* Save the BAR's; firmware doesn't restore these after EEH reset */
+               dn = pci_device_to_OF_node(dev);
+               eeh_save_bars(dev, PCI_DN(dn));
        }
 
 #ifdef DEBUG
        }
 }
 
+/* ------------------------------------------------------- */
+/** Save and restore of PCI BARs
+ *
+ * Although firmware will set up BARs during boot, it doesn't
+ * set up device BAR's after a device reset, although it will,
+ * if requested, set up bridge configuration. Thus, we need to
+ * configure the PCI devices ourselves.  
+ */
+
+/**
+ * __restore_bars - Restore the Base Address Registers
+ * Loads the PCI configuration space base address registers,
+ * the expansion ROM base address, the latency timer, and etc.
+ * from the saved values in the device node.
+ */
+static inline void __restore_bars (struct pci_dn *pdn)
+{
+       int i;
+
+       if (NULL==pdn->phb) return;
+       for (i=4; i<10; i++) {
+               rtas_write_config(pdn, i*4, 4, pdn->config_space[i]);
+       }
+
+       /* 12 == Expansion ROM Address */
+       rtas_write_config(pdn, 12*4, 4, pdn->config_space[12]);
+
+#define BYTE_SWAP(OFF) (8*((OFF)/4)+3-(OFF))
+#define SAVED_BYTE(OFF) (((u8 *)(pdn->config_space))[BYTE_SWAP(OFF)])
+
+       rtas_write_config (pdn, PCI_CACHE_LINE_SIZE, 1,
+                   SAVED_BYTE(PCI_CACHE_LINE_SIZE));
+
+       rtas_write_config (pdn, PCI_LATENCY_TIMER, 1,
+                   SAVED_BYTE(PCI_LATENCY_TIMER));
+
+       /* max latency, min grant, interrupt pin and line */
+       rtas_write_config(pdn, 15*4, 4, pdn->config_space[15]);
+}
+
+/**
+ * eeh_restore_bars - restore the PCI config space info
+ *
+ * This routine performs a recursive walk to the children
+ * of this device as well.
+ */
+void eeh_restore_bars(struct pci_dn *pdn)
+{
+       struct device_node *dn;
+       if (!pdn) 
+               return;
+       
+       if (! pdn->eeh_is_bridge)
+               __restore_bars (pdn);
+
+       dn = pdn->node->child;
+       while (dn) {
+               eeh_restore_bars (PCI_DN(dn));
+               dn = dn->sibling;
+       }
+}
+
+/**
+ * eeh_save_bars - save device bars
+ *
+ * Save the values of the device bars. Unlike the restore
+ * routine, this routine is *not* recursive. This is because
+ * PCI devices are added individuallly; but, for the restore,
+ * an entire slot is reset at a time.
+ */
+static void eeh_save_bars(struct pci_dev * pdev, struct pci_dn *pdn)
+{
+       int i;
+
+       if (!pdev || !pdn )
+               return;
+       
+       for (i = 0; i < 16; i++)
+               pci_read_config_dword(pdev, i * 4, &pdn->config_space[i]);
+
+       if (pdev->hdr_type == PCI_HEADER_TYPE_BRIDGE)
+               pdn->eeh_is_bridge = 1;
+}
+
+void
+rtas_configure_bridge(struct pci_dn *pdn)
+{
+       int token = rtas_token ("ibm,configure-bridge");
+       int rc;
+
+       if (token == RTAS_UNKNOWN_SERVICE)
+               return;
+       rc = rtas_call(token,3,1, NULL,
+                      pdn->eeh_config_addr,
+                      BUID_HI(pdn->phb->buid),
+                      BUID_LO(pdn->phb->buid));
+       if (rc) {
+               printk (KERN_WARNING "EEH: Unable to configure device bridge (%d) for %s\n",
+                       rc, pdn->node->full_name);
+       }
+}
+
 /* ------------------------------------------------------------- */
 /* The code below deals with enabling EEH for devices during  the
  * early boot sequence.  EEH must be enabled before any PCI probing
 void eeh_add_device_late(struct pci_dev *dev)
 {
        struct device_node *dn;
+       struct pci_dn *pdn;
 
        if (!dev || !eeh_subsystem_enabled)
                return;
 
        pci_dev_get (dev);
        dn = pci_device_to_OF_node(dev);
-       PCI_DN(dn)->pcidev = dev;
+       pdn = PCI_DN(dn);
+       pdn->pcidev = dev;
 
        pci_addr_cache_insert_device (dev);
+       eeh_save_bars(dev, pdn);
 }
 EXPORT_SYMBOL_GPL(eeh_add_device_late);
 
 
  */
 void rtas_set_slot_reset (struct pci_dn *);
 
+/** 
+ * eeh_restore_bars - Restore device configuration info.
+ *
+ * A reset of a PCI device will clear out its config space.
+ * This routines will restore the config space for this
+ * device, and is children, to values previously obtained
+ * from the firmware.
+ */
+void eeh_restore_bars(struct pci_dn *);
+
+/**
+ * rtas_configure_bridge -- firmware initialization of pci bridge
+ *
+ * Ask the firmware to configure all PCI bridges devices
+ * located behind the indicated node. Required after a
+ * pci device reset. Does essentially the same hing as
+ * eeh_restore_bars, but for brdges, and lets firmware 
+ * do the work.
+ */
+void rtas_configure_bridge(struct pci_dn *);
+
+int rtas_write_config(struct pci_dn *, int where, int size, u32 val);
+
 #endif
 
 #endif /* _ASM_POWERPC_PPC_PCI_H */