📄 prom.c
字号:
* On a CHRP we have an 8259 which is subordinate to * the openpic in the interrupt tree, but we want the * openpic's interrupt numbers offsetted, not the 8259's. * So we apply the offset if the controller is at the * root of the interrupt tree, i.e. has no interrupt-parent. * This doesn't cope with the general case of multiple * cascaded interrupt controllers, but then neither will * irq.c at the moment either. -- paulus */ if (num_interrupt_controllers > 1 && ic != NULL && get_property(ic, "interrupt-parent", NULL) == NULL) offset = 16; np->intrs[i].line = irq[0] + offset; if (n > 1) np->intrs[i].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"); } ints += intrcells; } return mem_start;}/* * When BootX makes a copy of the device tree from the MacOS * Name Registry, it is in the format we use but all of the pointers * are offsets from the start of the tree. * This procedure updates the pointers. */void __initrelocate_nodes(void){ unsigned long base; struct device_node *np; struct property *pp;#define ADDBASE(x) (x = (x)? ((typeof (x))((unsigned long)(x) + base)): 0) base = (unsigned long) boot_infos + boot_infos->deviceTreeOffset; allnodes = (struct device_node *)(base + 4); for (np = allnodes; np != 0; np = np->allnext) { ADDBASE(np->full_name); ADDBASE(np->properties); ADDBASE(np->parent); ADDBASE(np->child); ADDBASE(np->sibling); ADDBASE(np->allnext); for (pp = np->properties; pp != 0; pp = pp->next) { ADDBASE(pp->name); ADDBASE(pp->value); ADDBASE(pp->next); } }}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 __initmap_addr(struct device_node *np, unsigned long space, unsigned long addr){ int na; unsigned int *ranges; int rlen = 0; unsigned int type; type = (space >> 24) & 3; if (type == 0) return addr; while ((np = np->parent) != NULL) { if (strcmp(np->type, "pci") != 0) continue; /* PCI bridge: map the address through the ranges property */ na = prom_n_addr_cells(np); ranges = (unsigned int *) get_property(np, "ranges", &rlen); while ((rlen -= (na + 5) * sizeof(unsigned int)) >= 0) { if (((ranges[0] >> 24) & 3) == type && ranges[2] <= addr && addr - ranges[2] < ranges[na+4]) { /* ok, this matches, translate it */ addr += ranges[na+2] - ranges[2]; break; } ranges += na + 5; } } return addr;}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, *ip; 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 = map_addr(np, pci_addrs[i].addr.a_hi, 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); } if (use_of_interrupt_tree) return mem_start; ip = (int *) get_property(np, "AAPL,interrupts", &l); if (ip == 0 && np->parent) ip = (int *) get_property(np->parent, "AAPL,interrupts", &l); if (ip == 0) ip = (int *) get_property(np, "interrupts", &l); if (ip != 0) { np->intrs = (struct interrupt_info *) mem_start; np->n_intrs = l / sizeof(int); mem_start += np->n_intrs * sizeof(struct interrupt_info); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; np->intrs[i].sense = 1; } } return mem_start;}static unsigned long __initinterpret_dbdma_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec){ struct reg_property *rp; struct address_range *adr; unsigned long base_address; int i, l, *ip; struct device_node *db; base_address = 0; 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_property *) get_property(np, "reg", &l); if (rp != 0 && l >= sizeof(struct reg_property)) { i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property)) >= 0) { 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); } if (use_of_interrupt_tree) return mem_start; ip = (int *) get_property(np, "AAPL,interrupts", &l); if (ip == 0) ip = (int *) get_property(np, "interrupts", &l); if (ip != 0) { np->intrs = (struct interrupt_info *) mem_start; np->n_intrs = l / sizeof(int); mem_start += np->n_intrs * sizeof(struct interrupt_info); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; np->intrs[i].sense = 1; } } return mem_start;}static unsigned long __initinterpret_macio_props(struct device_node *np, unsigned long mem_start, int naddrc, int nsizec){ struct reg_property *rp; struct address_range *adr; unsigned long base_address; int i, l, *ip; struct device_node *db; base_address = 0; 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_property *) get_property(np, "reg", &l); if (rp != 0 && l >= sizeof(struct reg_property)) { i = 0; adr = (struct address_range *) mem_start; while ((l -= sizeof(struct reg_property)) >= 0) { 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); } if (use_of_interrupt_tree) return mem_start; ip = (int *) get_property(np, "interrupts", &l); if (ip == 0) ip = (int *) get_property(np, "AAPL,interrupts", &l); if (ip != 0) { np->intrs = (struct interrupt_info *) mem_start; np->n_intrs = l / sizeof(int); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; np->intrs[i].sense = 1; } mem_start += np->n_intrs * sizeof(struct interrupt_info); } 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, *ip; 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); } if (use_of_interrupt_tree) return mem_start; ip = (int *) get_property(np, "interrupts", &l); if (ip != 0) { np->intrs = (struct interrupt_info *) mem_start; np->n_intrs = l / (2 * sizeof(int)); mem_start += np->n_intrs * sizeof(struct interrupt_info); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; np->intrs[i].sense = *ip++; } } 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, *ip; 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 = (naddrc >= 2? rp[naddrc-2]: 2); 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); } if (use_of_interrupt_tree) return mem_start; ip = (int *) get_property(np, "AAPL,interrupts", &l); if (ip == 0) ip = (int *) get_property(np, "interrupts", &l); if (ip != 0) { np->intrs = (struct interrupt_info *) mem_start; np->n_intrs = l / sizeof(int); mem_start += np->n_intrs * sizeof(struct interrupt_info); for (i = 0; i < np->n_intrs; ++i) { np->intrs[i].line = *ip++; np->intrs[i].sense = 1; } } 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); if (!use_of_interrupt_tree) return; 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) { if (np->intrs[j].sense == 1) { senses[i-off] = (IRQ_SENSE_LEVEL | IRQ_POLARITY_NEGATIVE); } else { senses[i-off] = (IRQ_SENSE_EDGE | IRQ_POLARITY_POSITIVE); } } } }}/* * 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) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -