void __init fill_ebus_device(int node, struct linux_ebus_device *dev) { struct linux_prom_registers regs[PROMREG_MAX]; struct linux_ebus_child *child; int irqs[PROMINTR_MAX]; int i, n, len; dev->prom_node = node; prom_getstring(node, "name", dev->prom_name, sizeof(dev->prom_name)); printk(" [%s", dev->prom_name); len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", dev->prom_name, len, (int)sizeof(struct linux_prom_registers)); prom_halt(); } dev->num_addrs = len / sizeof(struct linux_prom_registers); for (i = 0; i < dev->num_addrs; i++) { n = (regs[i].which_io - 0x10) >> 2; dev->resource[i].start = dev->bus->self->resource[n].start; dev->resource[i].start += (unsigned long)regs[i].phys_addr; dev->resource[i].end = (dev->resource[i].start + (unsigned long)regs[i].reg_size - 1UL); dev->resource[i].flags = IORESOURCE_MEM; dev->resource[i].name = dev->prom_name; request_resource(&dev->bus->self->resource[n], &dev->resource[i]); } len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); if ((len == -1) || (len == 0)) { dev->num_irqs = 0; } else { dev->num_irqs = len / sizeof(irqs[0]); for (i = 0; i < dev->num_irqs; i++) { struct pci_pbm_info *pbm = dev->bus->parent; struct pci_controller_info *p = pbm->parent; if (ebus_intmap_match(dev->bus, ®s[0], &irqs[i]) != -1) { dev->irqs[i] = p->irq_build(p, dev->bus->self, irqs[i]); } else { /* If we get a bogus interrupt property, just * record the raw value instead of punting. */ dev->irqs[i] = irqs[i]; } } } if ((node = prom_getchild(node))) { printk(" ->"); dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); child = dev->children; child->next = 0; child->parent = dev; child->bus = dev->bus; fill_ebus_child(node, ®s[0], child, child_regs_nonstandard(dev)); while ((node = prom_getsibling(node))) { child->next = ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = 0; child->parent = dev; child->bus = dev->bus; fill_ebus_child(node, ®s[0], child, child_regs_nonstandard(dev)); } } printk("]"); }
__initfunc(void fill_ebus_device(int node, struct linux_ebus_device *dev)) { struct linux_prom_registers regs[PROMREG_MAX]; struct linux_ebus_child *child; int irqs[PROMINTR_MAX]; char lbuf[128]; int i, n, len; dev->prom_node = node; prom_getstring(node, "name", lbuf, sizeof(lbuf)); strcpy(dev->prom_name, lbuf); len = prom_getproperty(node, "reg", (void *)regs, sizeof(regs)); if (len % sizeof(struct linux_prom_registers)) { prom_printf("UGH: proplen for %s was %d, need multiple of %d\n", dev->prom_name, len, (int)sizeof(struct linux_prom_registers)); panic(__FUNCTION__); } dev->num_addrs = len / sizeof(struct linux_prom_registers); for (i = 0; i < dev->num_addrs; i++) { n = (regs[i].which_io - 0x10) >> 2; dev->base_address[i] = dev->bus->self->base_address[n]; dev->base_address[i] += (unsigned long)regs[i].phys_addr; } len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); if ((len == -1) || (len == 0)) { dev->num_irqs = 0; } else { dev->num_irqs = len / sizeof(irqs[0]); for (i = 0; i < dev->num_irqs; i++) { ebus_intmap_match(dev->bus, ®s[0], &irqs[i]); dev->irqs[i] = psycho_irq_build(dev->bus->parent, dev->bus->self, irqs[i]); } } #ifdef DEBUG_FILL_EBUS_DEV dprintf("'%s': address%s\n", dev->prom_name, dev->num_addrs > 1 ? "es" : ""); for (i = 0; i < dev->num_addrs; i++) dprintf(" %016lx\n", dev->base_address[i]); if (dev->num_irqs) { dprintf(" IRQ%s", dev->num_irqs > 1 ? "s" : ""); for (i = 0; i < dev->num_irqs; i++) dprintf(" %s", __irq_itoa(dev->irqs[i])); dprintf("\n"); } #endif if ((node = prom_getchild(node))) { dev->children = (struct linux_ebus_child *) ebus_alloc(sizeof(struct linux_ebus_child)); child = dev->children; child->next = 0; child->parent = dev; child->bus = dev->bus; fill_ebus_child(node, ®s[0], child); while ((node = prom_getsibling(node))) { child->next = (struct linux_ebus_child *) ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = 0; child->parent = dev; child->bus = dev->bus; fill_ebus_child(node, ®s[0], child); } } }
static void __init fill_ebus_device(struct device_node *dp, struct linux_ebus_device *dev) { struct linux_ebus_child *child; struct of_device *op; int i, len; dev->prom_node = dp; printk(" [%s", dp->name); op = of_find_device_by_node(dp); if (!op) { dev->num_addrs = 0; dev->num_irqs = 0; } else { (void) of_get_property(dp, "reg", &len); dev->num_addrs = len / sizeof(struct linux_prom_registers); for (i = 0; i < dev->num_addrs; i++) memcpy(&dev->resource[i], &op->resource[i], sizeof(struct resource)); dev->num_irqs = op->num_irqs; for (i = 0; i < dev->num_irqs; i++) dev->irqs[i] = op->irqs[i]; } dev->ofdev.node = dp; dev->ofdev.dev.parent = &dev->bus->ofdev.dev; dev->ofdev.dev.bus = &ebus_bus_type; sprintf(dev->ofdev.dev.bus_id, "ebus[%08x]", dp->node); /* Register with core */ if (of_device_register(&dev->ofdev) != 0) printk(KERN_DEBUG "ebus: device registration error for %s!\n", dp->path_component_name); dp = dp->child; if (dp) { printk(" ->"); dev->children = ebus_alloc(sizeof(struct linux_ebus_child)); child = dev->children; child->next = NULL; child->parent = dev; child->bus = dev->bus; fill_ebus_child(dp, child, child_regs_nonstandard(dev)); while ((dp = dp->sibling) != NULL) { child->next = ebus_alloc(sizeof(struct linux_ebus_child)); child = child->next; child->next = NULL; child->parent = dev; child->bus = dev->bus; fill_ebus_child(dp, child, child_regs_nonstandard(dev)); } } printk("]"); }