__initfunc(void fill_ebus_child(int node, struct linux_prom_registers *preg, struct linux_ebus_child *dev)) { int regs[PROMREG_MAX]; int irqs[PROMREG_MAX]; char lbuf[128]; int i, 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)); dev->num_addrs = len / sizeof(regs[0]); for (i = 0; i < dev->num_addrs; i++) { if (regs[i] >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", dev->prom_name, len, dev->parent->num_addrs); panic(__FUNCTION__); } dev->base_address[i] = dev->parent->base_address[regs[i]]; } len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); if ((len == -1) || (len == 0)) { dev->num_irqs = 0; /* * Oh, well, some PROMs don't export interrupts * property to children of EBus devices... * * Be smart about PS/2 keyboard and mouse. */ if (!strcmp(dev->parent->prom_name, "8042")) { if (!strcmp(dev->prom_name, "kb_ps2")) { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[0]; } else { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[1]; } } } else { dev->num_irqs = len / sizeof(irqs[0]); for (i = 0; i < dev->num_irqs; i++) { ebus_intmap_match(dev->bus, preg, &irqs[i]); dev->irqs[i] = psycho_irq_build(dev->bus->parent, dev->bus->self, irqs[i]); } } #ifdef DEBUG_FILL_EBUS_DEV dprintf("child '%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 }
void __init fill_ebus_child(int node, struct linux_prom_registers *preg, struct linux_ebus_child *dev, int non_standard_regs) { int regs[PROMREG_MAX]; int irqs[PROMREG_MAX]; int i, 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)); dev->num_addrs = len / sizeof(regs[0]); if (non_standard_regs) { /* This is to handle reg properties which are not * in the parent relative format. One example are * children of the i2c device on CompactPCI systems. * * So, for such devices we just record the property * raw in the child resources. */ for (i = 0; i < dev->num_addrs; i++) dev->resource[i].start = regs[i]; } else { for (i = 0; i < dev->num_addrs; i++) { int rnum = regs[i]; if (rnum >= dev->parent->num_addrs) { prom_printf("UGH: property for %s was %d, need < %d\n", dev->prom_name, len, dev->parent->num_addrs); panic(__FUNCTION__); } dev->resource[i].start = dev->parent->resource[i].start; dev->resource[i].end = dev->parent->resource[i].end; dev->resource[i].flags = IORESOURCE_MEM; dev->resource[i].name = dev->prom_name; } } len = prom_getproperty(node, "interrupts", (char *)&irqs, sizeof(irqs)); if ((len == -1) || (len == 0)) { dev->num_irqs = 0; /* * Oh, well, some PROMs don't export interrupts * property to children of EBus devices... * * Be smart about PS/2 keyboard and mouse. */ if (!strcmp(dev->parent->prom_name, "8042")) { if (!strcmp(dev->prom_name, "kb_ps2")) { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[0]; } else { dev->num_irqs = 1; dev->irqs[0] = dev->parent->irqs[1]; } } } 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, preg, &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]; } } } }
__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); } } }
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("]"); }