if (model && !strcmp(model, "SUNW,simba")) return 0;
/* Do not do PCI specific frobbing if the * PCI bridge lacks a ranges property. We * want to pass it through up to the next * parent as-is, not with the PCI translate * method which chops off the top address cell.
*/ if (!of_property_present(np, "ranges")) return 0;
if (model && !strcmp(model, "SUNW,simba")) return 1;
/* Treat PCI busses lacking ranges property just like * simba.
*/ if (of_node_name_eq(np, "pci")) { if (!of_property_present(np, "ranges")) return 1;
}
return 0;
}
staticint of_bus_simba_map(u32 *addr, const u32 *range, int na, int ns, int pna)
{ return 0;
}
staticvoid of_bus_pci_count_cells(struct device_node *np, int *addrc, int *sizec)
{ if (addrc)
*addrc = 3; if (sizec)
*sizec = 2;
}
staticint of_bus_pci_map(u32 *addr, const u32 *range, int na, int ns, int pna)
{
u32 result[OF_MAX_ADDR_CELLS]; int i;
/* Check address type match */ if (!((addr[0] ^ range[0]) & 0x03000000)) goto type_match;
/* Special exception, we can map a 64-bit address into * a 32-bit range.
*/ if ((addr[0] & 0x03000000) == 0x03000000 &&
(range[0] & 0x03000000) == 0x02000000) goto type_match;
return -EINVAL;
type_match: if (of_out_of_range(addr + 1, range + 1, range + na + pna,
na - 1, ns)) return -EINVAL;
/* Start with the parent range base. */
memcpy(result, range + na, pna * 4);
/* Add in the child address offset, skipping high cell. */ for (i = 0; i < na - 1; i++)
result[pna - 1 - i] +=
(addr[na - 1 - i] -
range[na - 1 - i]);
/* For PCI, we override whatever child busses may have used. */
flags = 0; switch((w >> 24) & 0x03) { case 0x01:
flags |= IORESOURCE_IO; break;
case 0x02: /* 32 bits */ case 0x03: /* 64 bits */
flags |= IORESOURCE_MEM; break;
} if (w & 0x40000000)
flags |= IORESOURCE_PREFETCH; return flags;
}
/* * FHC/Central bus specific translator. * * This is just needed to hard-code the address and size cell * counts. 'fhc' and 'central' nodes lack the #address-cells and * #size-cells properties, and if you walk to the root on such * Enterprise boxes all you'll get is a #size-cells of 2 which is * not what we want to use.
*/ staticint of_bus_fhc_match(struct device_node *np)
{ return of_node_name_eq(np, "fhc") ||
of_node_name_eq(np, "central");
}
staticstruct of_bus *of_match_bus(struct device_node *np)
{ int i;
for (i = 0; i < ARRAY_SIZE(of_busses); i ++) if (!of_busses[i].match || of_busses[i].match(np)) return &of_busses[i];
BUG(); return NULL;
}
staticint __init build_one_resource(struct device_node *parent, struct of_bus *bus, struct of_bus *pbus,
u32 *addr, int na, int ns, int pna)
{ const u32 *ranges; int rone, rlen;
ranges = of_get_property(parent, "ranges", &rlen); if (ranges == NULL || rlen == 0) {
u32 result[OF_MAX_ADDR_CELLS]; int i;
memset(result, 0, pna * 4); for (i = 0; i < na; i++)
result[pna - 1 - i] =
addr[na - 1 - i];
memcpy(addr, result, pna * 4); return 0;
}
/* Now walk through the ranges */
rlen /= 4;
rone = na + pna + ns; for (; rlen >= rone; rlen -= rone, ranges += rone) { if (!bus->map(addr, ranges, na, ns, pna)) return 0;
}
/* When we miss an I/O space match on PCI, just pass it up * to the next PCI bridge and/or controller.
*/ if (!strcmp(bus->name, "pci") &&
(addr[0] & 0x03000000) == 0x01000000) return 0;
return 1;
}
staticint __init use_1to1_mapping(struct device_node *pp)
{ /* If we have a ranges property in the parent, use it. */ if (of_property_present(pp, "ranges")) return 0;
/* If the parent is the dma node of an ISA bus, pass * the translation up to the root. * * Some SBUS devices use intermediate nodes to express * hierarchy within the device itself. These aren't * real bus nodes, and don't have a 'ranges' property. * But, we should still pass the translation work up * to the SBUS itself.
*/ if (of_node_name_eq(pp, "dma") ||
of_node_name_eq(pp, "espdma") ||
of_node_name_eq(pp, "ledma") ||
of_node_name_eq(pp, "lebuffer")) return 0;
/* Similarly for all PCI bridges, if we get this far * it lacks a ranges property, and this will include * cases like Simba.
*/ if (of_node_name_eq(pp, "pci")) return 0;
next:
imap += (na + 3);
} if (i == imlen) { /* Psycho and Sabre PCI controllers can have 'interrupt-map' * properties that do not include the on-board device * interrupts. Instead, the device's 'interrupts' property * is already a fully specified INO value. * * Handle this by deciding that, if we didn't get a * match in the parent's 'interrupt-map', and the * parent is an IRQ translator, then use the parent as * our IRQ controller.
*/ if (pp->irq_trans) return pp;
if (pp->irq_trans) { /* Derived from Table 8-3, U2P User's Manual. This branch * is handling a PCI controller that lacks a proper set of * interrupt-map and interrupt-map-mask properties. The * Ultra-E450 is one example. * * The bit layout is BSSLL, where: * B: 0 on bus A, 1 on bus B * D: 2-bit slot number, derived from PCI device number as * (dev - 1) for bus A, or (dev - 2) for bus B * L: 2-bit line number
*/ if (bus & 0x80) { /* PBM-A */
bus = 0x00;
slot = (slot - 1) << 2;
} else { /* PBM-B */
bus = 0x10;
slot = (slot - 2) << 2;
}
irq -= 1;
ret = (bus | slot | irq);
} else { /* Going through a PCI-PCI bridge that lacks a set of * interrupt-map and interrupt-map-mask properties.
*/
ret = ((irq - 1 + (slot & 3)) & 3) + 1;
}
if (dp->irq_trans) {
irq = dp->irq_trans->irq_build(dp, irq,
dp->irq_trans->data);
if (of_irq_verbose)
printk("%pOF: direct translate %x --> %x\n",
dp, orig_irq, irq);
goto out;
}
/* Something more complicated. Walk up to the root, applying * interrupt-map or bus specific translations, until we hit * an IRQ translator. * * If we hit a bus type or situation we cannot handle, we * stop and assume that the original IRQ number was in a * format which has special meaning to its immediate parent.
*/
pp = dp->parent;
ip = NULL; while (pp) { constvoid *imap, *imsk; int imlen;
irq = of_get_property(dp, "interrupts", &len); if (irq) {
op->archdata.num_irqs = len / 4;
/* Prevent overrunning the op->irqs[] array. */ if (op->archdata.num_irqs > PROMINTR_MAX) {
printk(KERN_WARNING "%pOF: Too many irqs (%d), " "limiting to %d.\n",
dp, op->archdata.num_irqs, PROMINTR_MAX);
op->archdata.num_irqs = PROMINTR_MAX;
}
memcpy(op->archdata.irqs, irq, op->archdata.num_irqs * 4);
} else {
op->archdata.num_irqs = 0;
}
build_device_resources(op, parent); for (i = 0; i < op->archdata.num_irqs; i++)
op->archdata.irqs[i] = build_one_device_irq(op, parent, op->archdata.irqs[i]);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.