summaryrefslogtreecommitdiff
path: root/sys/arch/macppc/pci
diff options
context:
space:
mode:
authorDale Rahn <drahn@cvs.openbsd.org>2002-03-02 17:44:59 +0000
committerDale Rahn <drahn@cvs.openbsd.org>2002-03-02 17:44:59 +0000
commit06ddcd92881ed39834be90d247e41ca803db55a9 (patch)
treee319b4ac2453198cd59f64ccccc565dc89ba2575 /sys/arch/macppc/pci
parentac829049a09dcce9c6ad4e1815bd4965bd6f79ca (diff)
cleanup.
Code reorganization to support pci-pci bridges on the interrupt fixup code. Interrupts on devices behind pci-pci bridges should not be configured properly.
Diffstat (limited to 'sys/arch/macppc/pci')
-rw-r--r--sys/arch/macppc/pci/mpcpcibus.c128
1 files changed, 71 insertions, 57 deletions
diff --git a/sys/arch/macppc/pci/mpcpcibus.c b/sys/arch/macppc/pci/mpcpcibus.c
index a0cacce7eaf..79124385a8e 100644
--- a/sys/arch/macppc/pci/mpcpcibus.c
+++ b/sys/arch/macppc/pci/mpcpcibus.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mpcpcibus.c,v 1.6 2002/01/26 20:52:59 drahn Exp $ */
+/* $OpenBSD: mpcpcibus.c,v 1.7 2002/03/02 17:44:58 drahn Exp $ */
/*
* Copyright (c) 1997 Per Fogelstrom
@@ -84,7 +84,7 @@ void mpc_intr_disestablish __P((void *, void *));
int mpc_ether_hw_addr __P((struct ppc_pci_chipset *, u_int8_t *));
u_int32_t mpc_gen_config_reg __P((void *cpv, pcitag_t tag, int offset));
int of_ether_hw_addr __P((struct ppc_pci_chipset *, u_int8_t *));
-int find_node_intr __P((int node, u_int32_t *addr, u_int32_t *intr));
+int find_node_intr (int parent, u_int32_t *addr, u_int32_t *intr);
u_int32_t pci_iack __P((void));
struct cfattach mpcpcibr_ca = {
@@ -518,16 +518,14 @@ mpcpcibrattach(parent, self, aux)
for (node = OF_child(of_node); node; node = nn)
{
- {
- char name[32];
- int len;
- len = OF_getprop(node, "name", name,
- sizeof(name));
- name[len] = 0;
-#if 0
- printf("checking node %s\n", name);
+ char name[32];
+ int len;
+ len = OF_getprop(node, "name", name,
+ sizeof(name));
+ name[len] = 0;
+#ifdef DEBUG_FIXUP
+ printf("checking node %s", name);
#endif
- }
fix_node_irq(node, &pba);
/* iterate section */
@@ -566,47 +564,66 @@ mpcpcibrattach(parent, self, aux)
* Find PCI IRQ from OF
*/
int
-find_node_intr(node, addr, intr)
- int node;
- u_int32_t *addr, *intr;
+find_node_intr(int parent, u_int32_t *addr, u_int32_t *intr)
{
- int parent, iparent, len, mlen;
- int match, i;
- u_int32_t map[64], *mp;
+ int iparent, len, mlen, n_mlen;
+ int match, i, step;
+ u_int32_t map[144], *mp, *mp1;
u_int32_t imask[8], maskedaddr[8];
- u_int32_t icells;
-
- len = OF_getprop(node, "AAPL,interrupts", intr, 4);
- if (len == 4)
- return 1;
- parent = OF_parent(node);
len = OF_getprop(parent, "interrupt-map", map, sizeof(map));
mlen = OF_getprop(parent, "interrupt-map-mask", imask, sizeof(imask));
+#ifdef DEBUG_FIXUP
+ printf("parent %x len %x mlen %x\n", parent, len, mlen);
+#endif
if ((len == -1) || (mlen == -1))
goto nomap;
- for (i = 0; i < (mlen / 4); i++) {
+ n_mlen = mlen/sizeof(u_int32_t);
+ for (i = 0; i < n_mlen; i++) {
maskedaddr[i] = addr[i] & imask[i];
}
mp = map;
+ /* calculate step size of interrupt-map
+ * -- assumes that iparent will be same for all nodes
+ */
+ iparent = mp[n_mlen];
+ step = 0;
+ for (i = (n_mlen)+1; i < len; i++) {
+ if (mp[i] == iparent) {
+ step = i - (n_mlen);
+ break;
+ }
+ }
+ if (step == 0) {
+ /* unable to determine step size */
+ return -1;
+ }
+
while (len > mlen) {
+#ifdef DEBUG_FIXUP
+ printf ("[%x %x %x %x] [%x %x %x %x] %x\n",
+ maskedaddr[0], maskedaddr[1], maskedaddr[2], maskedaddr[3],
+ mp[0], mp[1], mp[2], mp[3], step);
+#endif
match = bcmp(maskedaddr, mp, mlen);
- mp += mlen / 4;
- len -= mlen;
- iparent = *mp++;
- if (OF_getprop(iparent, "#interrupt-cells", &icells, 4) != 4)
- return -1;
+ mp1 = mp + n_mlen;
if (match == 0) {
/* multiple irqs? */
- *intr = *mp;
+ if (step == 9) {
+ /* pci-pci bridge */
+ iparent = *mp1;
+ /* recurse with new 'addr' */
+ return find_node_intr(iparent, &mp1[1], intr);
+ } else {
+ *intr = mp1[1];
+ }
return 1;
}
- mp += icells;
- len -= icells * 4;
+ len -= step * sizeof(u_int32_t);
+ mp += step;
}
- return -1;
nomap:
return -1;
}
@@ -624,6 +641,7 @@ fix_node_irq(node, pba)
pcitag_t tag;
u_int32_t irq;
u_int32_t intr;
+ int parent;
pci_chipset_tag_t pc = pba->pba_pc;
@@ -631,18 +649,31 @@ fix_node_irq(node, pba)
if (len < sizeof(addr[0])) {
return;
}
- tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
- pcidev(addr[0].phys_hi),
- pcifunc(addr[0].phys_hi));
+
+ /* if this node has a AAPL,interrupts property, firmware
+ * has intialized the register correctly.
+ */
+ len = OF_getprop(node, "AAPL,interrupts", &intr, 4);
+ if (len != 4) {
+
+ parent = OF_parent(node);
+
+ /* we want the first interrupt, set size_hi to 1 */
+ addr[0].size_hi = 1;
+ if (find_node_intr(parent, &addr[0].phys_hi, &irq) == -1)
+ return;
+ }
/* program the interrupt line register with the value
* found in openfirmware
*/
- if (find_node_intr(node, &addr[0].phys_hi, &irq) == -1)
- return;
+
+ tag = pci_make_tag(pc, pcibus(addr[0].phys_hi),
+ pcidev(addr[0].phys_hi),
+ pcifunc(addr[0].phys_hi));
intr = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
-#if 0
- printf("changing interrupt from %d to %d\n",
+#ifdef DEBUG_FIXUP
+ printf("changing interrupt from %x to %x\n",
intr & PCI_INTERRUPT_LINE_MASK,
irq & PCI_INTERRUPT_LINE_MASK);
#endif
@@ -989,10 +1020,6 @@ mpc_intr_establish(lcv, ih, level, func, arg, name)
{
return (*intr_establish_func)(lcv, ih, IST_LEVEL, level, func, arg,
name);
-#if 0
- return isabr_intr_establish(NULL, ih, IST_LEVEL, level, func, arg,
- name);
-#endif
}
void
@@ -1002,19 +1029,6 @@ mpc_intr_disestablish(lcv, cookie)
/* XXX We should probably do something clever here.... later */
}
-#if 0
-void
-mpc_print_pci_stat()
-{
- u_int32_t stat;
-
- stat = mpc_cfg_read_4(cp, MPC106_PCI_CMD);
- printf("pci: status 0x%08x.\n", stat);
- stat = mpc_cfg_read_2(cp, MPC106_PCI_STAT);
- printf("pci: status 0x%04x.\n", stat);
-}
-#endif
-
u_int32_t
pci_iack()
{