prom.c
来自「linux2.6.16版本」· C语言 代码 · 共 1,974 行 · 第 1/4 页
C
1,974 行
lprop = (u64*)of_get_flat_dt_prop(node, "linux,crashkernel-size", NULL); if (lprop) crashk_res.end = crashk_res.start + *lprop - 1;#endif /* Retreive command line */ p = of_get_flat_dt_prop(node, "bootargs", &l); if (p != NULL && l > 0) strlcpy(cmd_line, p, min((int)l, COMMAND_LINE_SIZE));#ifdef CONFIG_CMDLINE if (l == 0 || (l == 1 && (*p) == 0)) strlcpy(cmd_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);#endif /* CONFIG_CMDLINE */ DBG("Command line is: %s\n", cmd_line); if (strstr(cmd_line, "mem=")) { char *p, *q; unsigned long maxmem = 0; for (q = cmd_line; (p = strstr(q, "mem=")) != 0; ) { q = p + 4; if (p > cmd_line && p[-1] != ' ') continue; maxmem = simple_strtoul(q, &q, 0); if (*q == 'k' || *q == 'K') { maxmem <<= 10; ++q; } else if (*q == 'm' || *q == 'M') { maxmem <<= 20; ++q; } else if (*q == 'g' || *q == 'G') { maxmem <<= 30; ++q; } } memory_limit = maxmem; } /* break now */ return 1;}static int __init early_init_dt_scan_root(unsigned long node, const char *uname, int depth, void *data){ u32 *prop; if (depth != 0) return 0; prop = of_get_flat_dt_prop(node, "#size-cells", NULL); dt_root_size_cells = (prop == NULL) ? 1 : *prop; DBG("dt_root_size_cells = %x\n", dt_root_size_cells); prop = of_get_flat_dt_prop(node, "#address-cells", NULL); dt_root_addr_cells = (prop == NULL) ? 2 : *prop; DBG("dt_root_addr_cells = %x\n", dt_root_addr_cells); /* break now */ return 1;}static unsigned long __init dt_mem_next_cell(int s, cell_t **cellp){ cell_t *p = *cellp; unsigned long r; /* Ignore more than 2 cells */ while (s > sizeof(unsigned long) / 4) { p++; s--; } r = *p++;#ifdef CONFIG_PPC64 if (s > 1) { r <<= 32; r |= *(p++); s--; }#endif *cellp = p; return r;}static int __init early_init_dt_scan_memory(unsigned long node, const char *uname, int depth, void *data){ char *type = of_get_flat_dt_prop(node, "device_type", NULL); cell_t *reg, *endp; unsigned long l; /* We are scanning "memory" nodes only */ if (type == NULL) { /* * The longtrail doesn't have a device_type on the * /memory node, so look for the node called /memory@0. */ if (depth != 1 || strcmp(uname, "memory@0") != 0) return 0; } else if (strcmp(type, "memory") != 0) return 0; reg = (cell_t *)of_get_flat_dt_prop(node, "linux,usable-memory", &l); if (reg == NULL) reg = (cell_t *)of_get_flat_dt_prop(node, "reg", &l); if (reg == NULL) return 0; endp = reg + (l / sizeof(cell_t)); DBG("memory scan node %s, reg size %ld, data: %x %x %x %x,\n", uname, l, reg[0], reg[1], reg[2], reg[3]); while ((endp - reg) >= (dt_root_addr_cells + dt_root_size_cells)) { unsigned long base, size; base = dt_mem_next_cell(dt_root_addr_cells, ®); size = dt_mem_next_cell(dt_root_size_cells, ®); if (size == 0) continue; DBG(" - %lx , %lx\n", base, size);#ifdef CONFIG_PPC64 if (iommu_is_off) { if (base >= 0x80000000ul) continue; if ((base + size) > 0x80000000ul) size = 0x80000000ul - base; }#endif lmb_add(base, size); } return 0;}static void __init early_reserve_mem(void){ u64 base, size; u64 *reserve_map; reserve_map = (u64 *)(((unsigned long)initial_boot_params) + initial_boot_params->off_mem_rsvmap);#ifdef CONFIG_PPC32 /* * Handle the case where we might be booting from an old kexec * image that setup the mem_rsvmap as pairs of 32-bit values */ if (*reserve_map > 0xffffffffull) { u32 base_32, size_32; u32 *reserve_map_32 = (u32 *)reserve_map; while (1) { base_32 = *(reserve_map_32++); size_32 = *(reserve_map_32++); if (size_32 == 0) break; DBG("reserving: %x -> %x\n", base_32, size_32); lmb_reserve(base_32, size_32); } return; }#endif while (1) { base = *(reserve_map++); size = *(reserve_map++); if (size == 0) break; DBG("reserving: %llx -> %llx\n", base, size); lmb_reserve(base, size); }#if 0 DBG("memory reserved, lmbs :\n"); lmb_dump_all();#endif}void __init early_init_devtree(void *params){ DBG(" -> early_init_devtree()\n"); /* Setup flat device-tree pointer */ initial_boot_params = params; /* Retrieve various informations from the /chosen node of the * device-tree, including the platform type, initrd location and * size, TCE reserve, and more ... */ of_scan_flat_dt(early_init_dt_scan_chosen, NULL); /* Scan memory nodes and rebuild LMBs */ lmb_init(); of_scan_flat_dt(early_init_dt_scan_root, NULL); of_scan_flat_dt(early_init_dt_scan_memory, NULL); lmb_enforce_memory_limit(memory_limit); lmb_analyze(); DBG("Phys. mem: %lx\n", lmb_phys_mem_size()); /* Reserve LMB regions used by kernel, initrd, dt, etc... */ lmb_reserve(PHYSICAL_START, __pa(klimit) - PHYSICAL_START);#ifdef CONFIG_CRASH_DUMP lmb_reserve(0, KDUMP_RESERVE_LIMIT);#endif early_reserve_mem(); DBG("Scanning CPUs ...\n"); /* Retreive CPU related informations from the flat tree * (altivec support, boot CPU ID, ...) */ of_scan_flat_dt(early_init_dt_scan_cpus, NULL); DBG(" <- early_init_devtree()\n");}#undef printkintprom_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;}EXPORT_SYMBOL(prom_n_addr_cells);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;}EXPORT_SYMBOL(prom_n_size_cells);/** * Work out the sense (active-low level / active-high edge) * of each interrupt from the device tree. */void __init prom_get_irq_senses(unsigned char *senses, int off, int max){ struct device_node *np; int i, j; /* default to level-triggered */ memset(senses, IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE, 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;}EXPORT_SYMBOL(find_devices);/** * 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; return head;}EXPORT_SYMBOL(find_type_devices);/** * Returns all nodes linked together */struct device_node *find_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 = NULL; return head;}EXPORT_SYMBOL(find_all_nodes);/** Checks if the given "compat" string matches one of the strings in * the device's "compatible" property */int device_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;}EXPORT_SYMBOL(device_is_compatible);/** * Indicates whether the root node has a given value in its * compatible property. */int machine_is_compatible(const char *compat){ struct device_node *root; int rc = 0; root = of_find_node_by_path("/"); if (root) { rc = device_is_compatible(root, compat); of_node_put(root); } return rc;}EXPORT_SYMBOL(machine_is_compatible);/** * 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 = NULL; return head;}EXPORT_SYMBOL(find_compatible_devices);/** * 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;}EXPORT_SYMBOL(find_path_device);/******* * * New implementation of the OF "find" APIs, return a refcounted * object, call of_node_put() when done. The device tree and list * are protected by a rw_lock. * * Note that property management will need some locking as well, * this isn't dealt with yet. * *******//** * of_find_node_by_name - Find a node by its "name" property * @from: The node to start searching from or NULL, the node * you pass will not be searched, only the next one * will; typically, you pass what the previous call * returned. of_node_put() will be called on it * @name: The name string to match against * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */struct device_node *of_find_node_by_name(struct device_node *from, const char *name){ struct device_node *np; read_lock(&devtree_lock); np = from ? from->allnext : allnodes; for (; np != NULL; np = np->allnext) if (np->name != NULL && strcasecmp(np->name, name) == 0 && of_node_get(np)) break; if (from) of_node_put(from); read_unlock(&devtree_lock); return np;}EXPORT_SYMBOL(of_find_node_by_name);/** * of_find_node_by_type - Find a node by its "device_type" property * @from: The node to start searching from or NULL, the node * you pass will not be searched, only the next one * will; typically, you pass what the previous call * returned. of_node_put() will be called on it * @name: The type string to match against * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */struct device_node *of_find_node_by_type(struct device_node *from, const char *type){ struct device_node *np; read_lock(&devtree_lock); np = from ? from->allnext : allnodes; for (; np != 0; np = np->allnext) if (np->type != 0 && strcasecmp(np->type, type) == 0 && of_node_get(np)) break; if (from) of_node_put(from); read_unlock(&devtree_lock); return np;}EXPORT_SYMBOL(of_find_node_by_type);/** * of_find_compatible_node - Find a node based on type and one of the * tokens in its "compatible" property * @from: The node to start searching from or NULL, the node * you pass will not be searched, only the next one * will; typically, you pass what the previous call * returned. of_node_put() will be called on it * @type: The type string to match "device_type" or NULL to ignore * @compatible: The string to match to one of the tokens in the device * "compatible" list. * * Returns a node pointer with refcount incremented, use * of_node_put() on it when done. */struct device_node *of_find_compatible_node(struct device_node *from,
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?