patch-2.4.21 linux-2.4.21/arch/ppc/kernel/prom.c

Next file: linux-2.4.21/arch/ppc/kernel/prom_init.c
Previous file: linux-2.4.21/arch/ppc/kernel/process.c
Back to the patch index
Back to the overall index

diff -urN linux-2.4.20/arch/ppc/kernel/prom.c linux-2.4.21/arch/ppc/kernel/prom.c
@@ -1,7 +1,4 @@
 /*
- * BK Id: %F% %I% %G% %U% %#%
- */
-/*
  * Procedures for interfacing to the Open Firmware PROM on
  * Power Macintosh computers.
  *
@@ -506,6 +503,38 @@
 }
 
 static unsigned long __init
+map_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 __init
 interpret_pci_props(struct device_node *np, unsigned long mem_start,
 		    int naddrc, int nsizec)
 {
@@ -519,9 +548,9 @@
 		i = 0;
 		adr = (struct address_range *) mem_start;
 		while ((l -= sizeof(struct pci_reg_property)) >= 0) {
-			/* XXX assumes PCI addresses mapped 1-1 to physical */
 			adr[i].space = pci_addrs[i].addr.a_hi;
-			adr[i].address = pci_addrs[i].addr.a_lo;
+			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;
 		}
@@ -758,8 +787,15 @@
 	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;
+			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);
+				}
+			}
 		}
 	}
 }

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)