+ r->start = r->end = 0;
+
+ /* Astro has 4 directed ranges. Not sure about Ike/Pluto/et al */
+ for (i=0; i<4; i++) {
+ int base, size;
+ unsigned long reg = sba->sba_hpa + i*0x18;
+
+ base = READ_REG32(reg + LMMIO_DIRECT0_BASE);
+ if ((base & 1) == 0)
+ continue; /* not enabled */
+
+ size = READ_REG32(reg + LMMIO_DIRECT0_ROUTE);
+
+ if ((size & (ROPES_PER_IOC-1)) != rope)
+ continue; /* directed down different rope */
+
+ r->start = (base & ~1UL) | PCI_F_EXTEND;
+ size = ~ READ_REG32(reg + LMMIO_DIRECT0_MASK);
+ r->end = r->start + size;
+ }
+}
+
+
+/**
+ * sba_distributed_lmmio - return portion of distributed LMMIO range
+ * @pa_dev: The parisc device.
+ * @r: resource PCI host controller wants start/end fields assigned.
+ *
+ * For the given parisc PCI controller, return portion of distributed LMMIO
+ * range. The distributed LMMIO is always present and it's just a question
+ * of the base address and size of the range.
+ */
+void sba_distributed_lmmio(struct parisc_device *pci_hba, struct resource *r )
+{
+ struct parisc_device *sba_dev = parisc_parent(pci_hba);
+ struct sba_device *sba = sba_dev->dev.driver_data;
+ char t = sba_dev->id.hw_type;
+ int base, size;
+ int rope = (pci_hba->hw_path & (ROPES_PER_IOC-1)); /* rope # */
+
+ if ((t!=HPHW_IOA) && (t!=HPHW_BCPORT))
+ BUG();
+
+ r->start = r->end = 0;
+
+ base = READ_REG32(sba->sba_hpa + LMMIO_DIST_BASE);
+ if ((base & 1) == 0) {
+ BUG(); /* Gah! Distr Range wasn't enabled! */
+ return;
+ }
+
+ r->start = (base & ~1UL) | PCI_F_EXTEND;
+
+ size = (~READ_REG32(sba->sba_hpa + LMMIO_DIST_MASK)) / ROPES_PER_IOC;
+ r->start += rope * (size + 1); /* adjust base for this rope */
+ r->end = r->start + size;