📄 prom.c
字号:
map_parent = *((phandle *)map); map+=1; map_size-=1; parent_node = find_phandle(map_parent); temp_isize = isize; temp_asize = 0; if (parent_node) { isizep = (unsigned int *)get_property(parent_node, "#interrupt-cells", &l); if (isizep) temp_isize = *isizep; asizep = (unsigned int *)get_property(parent_node, "#address-cells", &l); if (asizep && l == sizeof(unsigned int)) temp_asize = *asizep; } if (!found) { map += temp_isize + temp_asize; map_size -= temp_isize + temp_asize; } } if (found) { /* Mapped to a new parent. Use the reg and interrupts specified in * the map as the new search parameters. Then search from the parent. */ node = parent_node; reg = map; regpsize = temp_asize; interrupts = map + temp_asize; ipsize = temp_isize; continue; } } /* We look for an explicit interrupt-parent. */ parent = (phandle *)get_property(node, "interrupt-parent", &l); if (parent && (l == sizeof(phandle)) && (parent_node = find_phandle(*parent))) { node = parent_node; continue; } /* Default, get real parent */ node = node->parent; } while (node); return mem_start;}intprom_n_addr_cells(struct device_node* np){ int* ip; do { if (np->parent) np = np->parent; ip = (int *) get_property(np, "#address-cells", 0); 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", 0); if (ip != NULL) return *ip; } while (np->parent); /* No #size-cells property for the root node, default to 1 */ return 1;}static unsigned long __initinterpret_pci_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec){ 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) { 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_isa_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec){ 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) { adr[i].space = rp[i].space; adr[i].address = rp[i].address + (adr[i].space? 0: _ISA_MEM_BASE); 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){ 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) { 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;}/* * 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 = 0; 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 = 0; return head;}/* * Returns all nodes linked together */struct device_node * __openfirmwarefind_all_nodes(void){ struct device_node *head, **prevp, *np; prevp = &head; for (np = allnodes; np != 0; np = np->allnext) { *prevp = np; prevp = &np->next; } *prevp = 0; return head;}/* Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */intdevice_is_compatible(struct device_node *device, const char *compat){ const char* cp; int cplen, l; cp = (char *) get_property(device, "compatible", &cplen); if (cp == NULL) return 0; while (cplen > 0) { if (strncasecmp(cp, compat, strlen(compat)) == 0) return 1; l = strlen(cp) + 1; cp += l; cplen -= l; } return 0;}/* * Indicates whether the root node has a given value in its * compatible property. */intmachine_is_compatible(const char *compat){ struct device_node *root; root = find_path_device("/"); if (root == 0) return 0; return device_is_compatible(root, compat);}/* * Construct and return a list of the device_nodes with a given type * and compatible property. */struct device_node *find_compatible_devices(const char *type, const char *compat){ struct device_node *head, **prevp, *np; prevp = &head; for (np = allnodes; np != 0; np = np->allnext) { if (type != NULL && !(np->type != 0 && strcasecmp(np->type, type) == 0)) continue; if (device_is_compatible(np, compat)) { *prevp = np; prevp = &np->next; } } *prevp = 0; return head;}/* * Find the device_node with a given full_name. */struct device_node *find_path_device(const char *path){ struct device_node *np; for (np = allnodes; np != 0; np = np->allnext) if (np->full_name != 0 && strcasecmp(np->full_name, path) == 0) return np; return NULL;}/* * Find the device_node with a given phandle. */static struct device_node * __initfind_phandle(phandle ph){ struct device_node *np; for (np = allnodes; np != 0; np = np->allnext) if (np->node == ph) return np; return NULL;}/* * Find a property with a given name for a given node * and return the value. */unsigned char *get_property(struct device_node *np, const char *name, int *lenp){ struct property *pp; for (pp = np->properties; pp != 0; pp = pp->next) if (strcmp(pp->name, name) == 0) { if (lenp != 0) *lenp = pp->length; return pp->value; } return 0;}/* * Add a property to a node */void __openfirmwareprom_add_property(struct device_node* np, struct property* prop){ struct property **next = &np->properties; prop->next = NULL; while (*next) next = &(*next)->next; *next = prop;}#if 0void __openfirmwareprint_properties(struct device_node *np){ struct property *pp; char *cp; int i, n; for (pp = np->properties; pp != 0; pp = pp->next) { printk(KERN_INFO "%s", pp->name); for (i = strlen(pp->name); i < 16; ++i) printk(" "); cp = (char *) pp->value; for (i = pp->length; i > 0; --i, ++cp) if ((i > 1 && (*cp < 0x20 || *cp > 0x7e)) || (i == 1 && *cp != 0)) break; if (i == 0 && pp->length > 1) { /* looks like a string */ printk(" %s\n", (char *) pp->value); } else { /* dump it in hex */ n = pp->length; if (n > 64) n = 64; if (pp->length % 4 == 0) { unsigned int *p = (unsigned int *) pp->value; n /= 4; for (i = 0; i < n; ++i) { if (i != 0 && (i % 4) == 0) printk("\n "); printk(" %08x", *p++); } } else { unsigned char *bp = pp->value; for (i = 0; i < n; ++i) { if (i != 0 && (i % 16) == 0) printk("\n "); printk(" %02x", *bp++); } } printk("\n"); if (pp->length > 64) printk(" ... (length = %d)\n", pp->length); } }}#endifvoid __initabort(){#ifdef CONFIG_XMON xmon(NULL);#endif for (;;) prom_exit();}/* Verify bi_recs are good */static struct bi_record *prom_bi_rec_verify(struct bi_record *bi_recs){ struct bi_record *first, *last; if ( bi_recs == NULL || bi_recs->tag != BI_FIRST ) return NULL; last = (struct bi_record *)bi_recs->data[0]; if ( last == NULL || last->tag != BI_LAST ) return NULL; first = (struct bi_record *)last->data[0]; if ( first == NULL || first != bi_recs ) return NULL; return bi_recs;}static unsigned longprom_bi_rec_reserve(unsigned long mem){ unsigned long offset = reloc_offset(); struct prom_t *_prom = PTRRELOC(&prom); struct bi_record *rec; if ( _prom->bi_recs != NULL) { for ( rec=_prom->bi_recs; rec->tag != BI_LAST; rec=bi_rec_next(rec) ) { switch (rec->tag) {#ifdef CONFIG_BLK_DEV_INITRD case BI_INITRD: lmb_reserve(rec->data[0], rec->data[1]); break;#endif /* CONFIG_BLK_DEV_INITRD */ } } /* The next use of this field will be after relocation * is enabled, so convert this physical address into a * virtual address. */ _prom->bi_recs = PTRUNRELOC(_prom->bi_recs); } return mem;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -