prom.c
字号:
imap = (unsigned int *) get_property(p, "interrupt-map", &imaplen); if (imap == NULL) { p = intr_parent(p); continue; } imask = (unsigned int *) get_property(p, "interrupt-map-mask", NULL); if (imask == NULL) { printk("oops, %s has interrupt-map but no mask\n", p->full_name); return 0; } imaplen /= sizeof(unsigned int); match = 0; ipar = NULL; while (imaplen > 0 && !match) { /* check the child-interrupt field */ match = 1; for (i = 0; i < naddrc && match; ++i) match = ((reg[i] ^ imap[i]) & imask[i]) == 0; for (; i < naddrc + nintrc && match; ++i) match = ((ints[i-naddrc] ^ imap[i]) & imask[i]) == 0; imap += naddrc + nintrc; imaplen -= naddrc + nintrc; /* grab the interrupt parent */ ipar = find_phandle((phandle) *imap++); --imaplen; if (ipar == NULL) { printk("oops, no int parent %x in map of %s\n", imap[-1], p->full_name); return 0; } /* find the parent's # addr and intr cells */ ip = (unsigned int *) get_property(ipar, "#interrupt-cells", NULL); if (ip == NULL) { printk("oops, no #interrupt-cells on %s\n", ipar->full_name); return 0; } newintrc = *ip; ip = (unsigned int *) get_property(ipar, "#address-cells", NULL); newaddrc = (ip == NULL)? 0: *ip; imap += newaddrc + newintrc; imaplen -= newaddrc + newintrc; } if (imaplen < 0) { printk("oops, error decoding int-map on %s, len=%d\n", p->full_name, imaplen); return 0; } if (!match) {#ifdef DEBUG_IRQ printk("oops, no match in %s int-map for %s\n", p->full_name, np->full_name);#endif return 0; } p = ipar; naddrc = newaddrc; nintrc = newintrc; ints = imap - nintrc; reg = ints - naddrc; } if (p == NULL) {#ifdef DEBUG_IRQ printk("hmmm, int tree for %s doesn't have ctrler\n", np->full_name);#endif return 0; } *irq = ints; *ictrler = p; return nintrc;}static unsigned long __initfinish_node_interrupts(struct device_node *np, unsigned long mem_start, int measure_only){ unsigned int *ints; int intlen, intrcells, intrcount; int i, j, n; unsigned int *irq, virq; struct device_node *ic; ints = (unsigned int *) get_property(np, "interrupts", &intlen); if (ints == NULL) return mem_start; intrcells = prom_n_intr_cells(np); intlen /= intrcells * sizeof(unsigned int); np->intrs = (struct interrupt_info *) mem_start; mem_start += intlen * sizeof(struct interrupt_info); if (measure_only) return mem_start; intrcount = 0; for (i = 0; i < intlen; ++i, ints += intrcells) { n = map_interrupt(&irq, &ic, np, ints, intrcells); if (n <= 0) continue; /* don't map IRQ numbers under a cascaded 8259 controller */ if (ic && device_is_compatible(ic, "chrp,iic")) { np->intrs[intrcount].line = irq[0]; } else { virq = virt_irq_create_mapping(irq[0]); if (virq == NO_IRQ) { printk(KERN_CRIT "Could not allocate interrupt" " number for %s\n", np->full_name); continue; } np->intrs[intrcount].line = irq_offset_up(virq); } /* We offset irq numbers for the u3 MPIC by 128 in PowerMac */ if (systemcfg->platform == PLATFORM_POWERMAC && ic && ic->parent) { char *name = get_property(ic->parent, "name", NULL); if (name && !strcmp(name, "u3")) np->intrs[intrcount].line += 128; } np->intrs[intrcount].sense = 1; if (n > 1) np->intrs[intrcount].sense = irq[1]; if (n > 2) { printk("hmmm, got %d intr cells for %s:", n, np->full_name); for (j = 0; j < n; ++j) printk(" %d", irq[j]); printk("\n"); } ++intrcount; } np->n_intrs = intrcount; return mem_start;}static unsigned long __initinterpret_pci_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec, int measure_only){ struct address_range *adr; struct pci_reg_property *pci_addrs; int i, l; pci_addrs = (struct pci_reg_property *) get_property(np, "assigned-addresses", &l); if (pci_addrs != 0 && l >= sizeof(struct pci_reg_property)) { i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct pci_reg_property)) >= 0) { if (!measure_only) { adr[i].space = pci_addrs[i].addr.a_hi; adr[i].address = pci_addrs[i].addr.a_lo; adr[i].size = pci_addrs[i].size_lo; } ++i; } np->addrs = adr; np->n_addrs = i; mem_start += i * sizeof(struct address_range); } return mem_start;}static unsigned long __initinterpret_dbdma_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec, int measure_only){ struct reg_property32 *rp; struct address_range *adr; unsigned long base_address; int i, l; struct device_node *db; base_address = 0; if (!measure_only) { for (db = np->parent; db != NULL; db = db->parent) { if (!strcmp(db->type, "dbdma") && db->n_addrs != 0) { base_address = db->addrs[0].address; break; } } } rp = (struct reg_property32 *) get_property(np, "reg", &l); if (rp != 0 && l >= sizeof(struct reg_property32)) { i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property32)) >= 0) { if (!measure_only) { adr[i].space = 2; adr[i].address = rp[i].address + base_address; adr[i].size = rp[i].size; } ++i; } np->addrs = adr; np->n_addrs = i; mem_start += i * sizeof(struct address_range); } return mem_start;}static unsigned long __initinterpret_macio_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec, int measure_only){ struct reg_property32 *rp; struct address_range *adr; unsigned long base_address; int i, l; struct device_node *db; base_address = 0; if (!measure_only) { for (db = np->parent; db != NULL; db = db->parent) { if (!strcmp(db->type, "mac-io") && db->n_addrs != 0) { base_address = db->addrs[0].address; break; } } } rp = (struct reg_property32 *) get_property(np, "reg", &l); if (rp != 0 && l >= sizeof(struct reg_property32)) { i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property32)) >= 0) { if (!measure_only) { adr[i].space = 2; adr[i].address = rp[i].address + base_address; adr[i].size = rp[i].size; } ++i; } np->addrs = adr; np->n_addrs = i; mem_start += i * sizeof(struct address_range); } return mem_start;}static unsigned long __initinterpret_isa_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec, int measure_only){ struct isa_reg_property *rp; struct address_range *adr; int i, l; rp = (struct isa_reg_property *) get_property(np, "reg", &l); if (rp != 0 && l >= sizeof(struct isa_reg_property)) { i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property)) >= 0) { if (!measure_only) { adr[i].space = rp[i].space; adr[i].address = rp[i].address; adr[i].size = rp[i].size; } ++i; } np->addrs = adr; np->n_addrs = i; mem_start += i * sizeof(struct address_range); } return mem_start;}static unsigned long __initinterpret_root_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec, int measure_only){ struct address_range *adr; int i, l; unsigned int *rp; int rpsize = (naddrc + nsizec) * sizeof(unsigned int); rp = (unsigned int *) get_property(np, "reg", &l); if (rp != 0 && l >= rpsize) { i = 0; adr = (struct address_range *) mem_start; while ((l -= rpsize) >= 0) { if (!measure_only) { adr[i].space = 0; adr[i].address = rp[naddrc - 1]; adr[i].size = rp[naddrc + nsizec - 1]; } ++i; rp += naddrc + nsizec; } np->addrs = adr; np->n_addrs = i; mem_start += i * sizeof(struct address_range); } return mem_start;}static unsigned long __initfinish_node(struct device_node *np, unsigned long mem_start, interpret_func *ifunc, int naddrc, int nsizec, int measure_only){ struct device_node *child; int *ip; np->name = get_property(np, "name", NULL); np->type = get_property(np, "device_type", NULL); if (!np->name) np->name = "<NULL>"; if (!np->type) np->type = "<NULL>"; /* get the device addresses and interrupts */ if (ifunc != NULL) mem_start = ifunc(np, mem_start, naddrc, nsizec, measure_only); mem_start = finish_node_interrupts(np, mem_start, measure_only); /* Look for #address-cells and #size-cells properties. */ ip = (int *) get_property(np, "#address-cells", NULL); if (ip != NULL) naddrc = *ip; ip = (int *) get_property(np, "#size-cells", NULL); if (ip != NULL) nsizec = *ip; /* the f50 sets the name to 'display' and 'compatible' to what we * expect for the name -- Cort */ if (!strcmp(np->name, "display")) np->name = get_property(np, "compatible", NULL); if (!strcmp(np->name, "device-tree") || np->parent == NULL) ifunc = interpret_root_props; else if (np->type == 0) ifunc = NULL; else if (!strcmp(np->type, "pci") || !strcmp(np->type, "vci")) ifunc = interpret_pci_props; else if (!strcmp(np->type, "dbdma")) ifunc = interpret_dbdma_props; else if (!strcmp(np->type, "mac-io") || ifunc == interpret_macio_props) ifunc = interpret_macio_props; else if (!strcmp(np->type, "isa")) ifunc = interpret_isa_props; else if (!strcmp(np->name, "uni-n") || !strcmp(np->name, "u3")) ifunc = interpret_root_props; else if (!((ifunc == interpret_dbdma_props || ifunc == interpret_macio_props) && (!strcmp(np->type, "escc") || !strcmp(np->type, "media-bay")))) ifunc = NULL; for (child = np->child; child != NULL; child = child->sibling) mem_start = finish_node(child, mem_start, ifunc, naddrc, nsizec, measure_only); return mem_start;}/** * finish_device_tree is called once things are running normally * (i.e. with text and data mapped to the address they were linked at). * It traverses the device tree and fills in the name, type, * {n_}addrs and {n_}intrs fields of each node. */void __initfinish_device_tree(void){ unsigned long mem = klimit; virt_irq_init(); dev_tree_size = finish_node(allnodes, 0, NULL, 0, 0, 1); mem = (long)abs_to_virt(lmb_alloc(dev_tree_size, __alignof__(struct device_node))); if (finish_node(allnodes, mem, NULL, 0, 0, 0) != mem + dev_tree_size) BUG(); rtas.dev = of_find_node_by_name(NULL, "rtas");}intprom_n_addr_cells(struct device_node* np){ int* ip; do { if (np->parent) np = np->parent; ip = (int *) get_property(np, "#address-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); /* No #address-cells property for the root node, default to 1 */ return 1;}intprom_n_size_cells(struct device_node* np){ int* ip; do { if (np->parent) np = np->parent; ip = (int *) get_property(np, "#size-cells", NULL); if (ip != NULL) return *ip; } while (np->parent); /* No #size-cells property for the root node, default to 1 */ return 1;}/** * Work out the sense (active-low level / active-high edge) * of each interrupt from the device tree. */void __initprom_get_irq_senses(unsigned char *senses, int off, int max){ struct device_node *np; int i, j; /* default to level-triggered */ memset(senses, 1, max - off); for (np = allnodes; np != 0; np = np->allnext) { for (j = 0; j < np->n_intrs; j++) { i = np->intrs[j].line; if (i >= off && i < max) senses[i-off] = np->intrs[j].sense; } }}/** * Construct and return a list of the device_nodes with a given name. */struct device_node *find_devices(const char *name){ struct device_node *head, **prevp, *np; prevp = &head; for (np = allnodes; np != 0; np = np->allnext) { if (np->name != 0 && strcasecmp(np->name, name) == 0) { *prevp = np; prevp = &np->next; } } *prevp = NULL; return head;}/** * Construct and return a list of the device_nodes with a given type. */struct device_node *find_type_devices(const char *type){ struct device_node *head, **prevp, *np; prevp = &head; for (np = allnodes; np != 0; np = np->allnext) { if (np->type != 0 && strcasecmp(np->type, type) == 0) { *prevp = np; prevp = &np->next; } } *prevp = NULL; re
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -