Пример #1
0
__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
}
Пример #2
0
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];
			}
		}
	}
}
Пример #3
0
__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, &regs[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, &regs[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, &regs[0], child);
        }
    }
}
Пример #4
0
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, &regs[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, &regs[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, &regs[0],
					child, child_regs_nonstandard(dev));
		}
	}
	printk("]");
}