WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-ppc-devel

[XenPPC] [PATCH] open pic detection

Signed-off-by: Maria Butrico <butrico@xxxxxxxxxxxxxx>

summary:    open pic detection.

        Moved the open pic detection code from boot_of to its
        own location.  The cew code uses the OFD tree.

diff -r d16209a2476e xen/arch/ppc/Makefile
--- a/xen/arch/ppc/Makefile     Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/Makefile     Thu May 18 10:15:31 2006 -0400
@@ -36,6 +36,7 @@ obj-y += smp.o
 obj-y += smp.o
 obj-y += time.o
 obj-y += usercopy.o
+obj-y += find_mpic.o
 
 obj-$(debug) += 0opt.o
 obj-$(crash_debug) += gdbstub.o
diff -r d16209a2476e xen/arch/ppc/boot_of.c
--- a/xen/arch/ppc/boot_of.c    Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/boot_of.c    Thu May 18 10:15:31 2006 -0400
@@ -36,7 +36,6 @@ static char bootargs[256];
 static char bootargs[256];
 static char dom0args[256];
 
-extern unsigned long opic_addr;
 extern struct ns16550_defaults ns16550;
 
 #undef OF_DEBUG
@@ -920,31 +919,6 @@ static int __init boot_of_rtas(void)
     return 1;
 }
 
-static void __init boot_of_pic(void)
-{
-    int root;
-    int p;
-    u32 addr_cells = 1;
-    int rc;
-    u32 addr[2];
-
-    root = of_finddevice("/");
-    p = of_getchild(root);
-
-    /* code is writen to assume sizes of 1 */
-    of_getprop(root, "#address-cells", &addr_cells, sizeof (addr_cells));
-    rc = of_getprop(root, "platform-open-pic", addr, sizeof (addr));
-    if (rc <= 0) {
-        of_panic("cannot find the openpic\n");
-    }
-    opic_addr = addr[0];
-    if (addr_cells == 2) {
-        opic_addr <<= 32;
-        opic_addr |= addr[1];
-    }
-    of_printf("OF: found OpenPIC at: 0x%lx\n", opic_addr);
-}
-
 static void __init boot_of_dart(void)
 {
     int n;
@@ -1010,7 +984,6 @@ multiboot_info_t __init *boot_of_init(
     boot_of_serial();
     boot_of_cpus();
     boot_of_rtas();
-    boot_of_pic();
     boot_of_dart();
 
     /* end of OF */
diff -r d16209a2476e xen/arch/ppc/external.c
--- a/xen/arch/ppc/external.c   Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/external.c   Thu May 18 10:15:31 2006 -0400
@@ -26,6 +26,7 @@
 #include <asm/current.h>
 #include <asm/hardirq.h>
 #include <asm/mpic.h>
+#include "find_mpic.h"
 
 #undef DEBUG
 #ifdef DEBUG
@@ -38,7 +39,6 @@ extern void do_IRQ(struct cpu_user_regs 
 
 int vector_irq[NR_VECTORS] __read_mostly = { [0 ... NR_VECTORS - 1] = -1};
 
-unsigned long opic_addr;
 unsigned long io_apic_irqs;
 int ioapic_ack_new = 1;
 
@@ -166,7 +166,7 @@ static void xen_set_affinity(unsigned in
     }
 }
 
-void init_IRQ(void)
+void init_IRQ(unsigned long oftree)
 {
     unsigned int isu_size;
     unsigned int irq_offset;
@@ -188,9 +188,18 @@ void init_IRQ(void)
     senses = NULL;
     senses_count = 0;
 
+
+    if (find_mpic(oftree)) {
+        printk("%s: ERROR: Could not find open pic.\n", __func__);
+        return;
+    } else {
+        unsigned long opic_addr = get_mpic_address();
+        unsigned int opic_flags = get_mpic_flags();
+
     mpic = mpic_alloc(opic_addr,
-                      MPIC_PRIMARY | MPIC_BIG_ENDIAN |
-                      MPIC_BROKEN_U3 | MPIC_WANTS_RESET,
+                      MPIC_PRIMARY | 
+                      MPIC_BROKEN_U3 | MPIC_WANTS_RESET |
+                      opic_flags,
                       isu_size, irq_offset, irq_count,
                       ipi_offset, senses, senses_count, "Xen-U3-MPIC");
 
@@ -219,6 +228,7 @@ void init_IRQ(void)
        mpic->hc_irq.set_affinity = xen_set_affinity;
 
     printk("%s: success\n", __func__);
+    }
 }
 
 void ack_APIC_irq(void) {
diff -r d16209a2476e xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c      Wed May 17 17:57:54 2006 -0400
+++ b/xen/arch/ppc/setup.c      Thu May 18 10:15:31 2006 -0400
@@ -37,6 +37,7 @@
 #include <asm/debugger.h>
 #include <asm/delay.h>
 
+#define DEBUG
 unsigned long xenheap_phys_end;
 
 /* opt_noht: If true, Hyperthreading is ignored. */
@@ -73,7 +74,7 @@ extern char exception_vectors_end[];
 
 /* move us to a header file */
 extern void initialize_keytable(void);
-extern void init_IRQ(void);
+extern void init_IRQ(unsigned long oftree);
 
 int is_kernel_text(unsigned long addr)
 {
@@ -115,7 +116,7 @@ static void __init start_of_day(void)
 {
     struct domain *idle_domain;
 
-    init_IRQ();
+    init_IRQ(oftree);
 
     scheduler_init();
 
@@ -188,7 +189,7 @@ static void __init __start_xen(multiboot
     modules_start = mod[0].mod_start;
     modules_size = mod[mbi->mods_count-1].mod_end - mod[0].mod_start;
 
-    /* OF dev tree is tthe last module */
+    /* OF dev tree is the last module */
     oftree = mod[mbi->mods_count-1].mod_start;
     oftree_end = mod[mbi->mods_count-1].mod_end;
     oftree_len = oftree_end - oftree;
diff -r d16209a2476e xen/arch/ppc/find_mpic.c
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/arch/ppc/find_mpic.c  Thu May 18 10:15:31 2006 -0400
@@ -0,0 +1,310 @@
+
+#include <xen/config.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/compile.h>
+#include <public/of-devtree.h>
+#include <asm/mpic.h>
+
+#undef DEBUG
+#undef NOSERIAL
+#ifdef DEBUG
+    #ifdef NOSERIAL
+    int of_printf(const char *fmt, ...)
+            __attribute__ ((format (printf, 1, 2)));
+    #define DBG(fmt...) of_printf(fmt)
+    #else
+    #define DBG(fmt...) printk(fmt)
+    #endif  /* #ifdef NOSERIAL */
+#else
+#define DBG(fmt...)
+#endif
+
+#define PANIC(fmt...) DBG(fmt)
+
+unsigned long opic_addr;
+unsigned int opic_flags;
+
+
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ *
+ * The number of integers in each size entry is
+ * determined by the value of the #size-cells property of this node (the node 
in which the ranges property appears)
+ * or 1 if the #size-cells property is absent.
+ *
+ *
+ * pg 177, property "reg"
+ *
+ * The number of integers in each size entry is determined by the value of the 
"#size-cells" property in the parent node.
+ * If the parent node has no such property, the value is one.
+ */
+static unsigned long reg2(void *oft_p, ofdn_t c)
+{
+    int rc;
+    /* the struct isa_reg_property is for a value of 2 for #address-cells and a
+     * value of 1 for #size-cells (of the parent).  
+     */
+    struct isa_reg_property {
+        u32 space;
+        u32 address;
+        u32 size;
+    } isa_reg;
+
+    rc = ofd_getprop(oft_p, c, "reg", &isa_reg, sizeof(isa_reg));
+
+    DBG("%s: reg property address=0x%08x  size=0x%08x\n", __func__,
+                    isa_reg.address, isa_reg.size);
+    return isa_reg.address;
+}
+
+static unsigned long reg1(void *oft_p, ofdn_t c)
+{
+    int rc;
+    /* the struct reg_property32 is for a value of 1 for #address-cells and
+     * a value of 1 for #size-cells.
+     */
+    struct reg_property32 {
+        u32 address;
+        u32 size;
+    } reg;
+
+    rc = ofd_getprop(oft_p, c, "reg", &reg, sizeof(reg));
+
+    DBG("%s: reg property address=0x%08x  size=0x%08x\n", __func__,
+                        reg.address, reg.size);
+    return reg.address;
+}
+
+static unsigned long find_reg_addr_from_node(void *oft_p, ofdn_t c)
+{
+    int p_len;
+    unsigned long reg_addr = 0;
+    u32 size_c = 1;
+    u32 addr_c = 2;
+    ofdn_t parent;
+
+    if (c == OFD_ROOT) {
+        parent = c;
+    } else {
+        parent = ofd_node_parent(oft_p, c);
+    }
+
+    p_len = ofd_getprop(oft_p, parent, "#size-cells", &size_c, sizeof(size_c));
+    DBG("%s size is %d\n", __func__, size_c);
+
+    p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c, 
sizeof(addr_c));
+    DBG("%s address is %d\n", __func__, addr_c);
+
+    if ( 1 != size_c ) {
+        PANIC("Unsupported size for reg property\n");
+    }
+    
+    if ( 1 == addr_c) {
+        reg_addr = reg1(oft_p, c);
+    } else if ( 2 == addr_c ) {
+        reg_addr = reg2(oft_p, c);
+    } else {
+        PANIC("Unsupported address size for reg property\n");
+    }
+    DBG("%s: address 0x%lx\n", __func__, reg_addr);
+    return reg_addr;
+}
+
+/*
+ * from OF_IEEE_1275
+ *
+ * pg 175, property "ranges"
+ * 
+ * The ranges property value is a sequence of
+ * child-phys parent-phys size
+ * specifications. Child-phys is an address, encoded as with encode-phys, in 
the child address space. Parent-phys is an
+ * address (likewise encoded as with encode-phys) in the parent address space. 
Size is a list of integers, each encoded as
+ * with encode-int, denoting the length of the child's address range.
+ */
+static unsigned long find_ranges_addr_from_node(void *oft_p, ofdn_t c)
+{
+    unsigned long ranges_addr = 0;
+    int ranges_i;
+    ofdn_t parent;
+    u32 addr_c = 2;
+    u32 ranges[64];
+    int p_len;
+
+    parent = ofd_node_parent(oft_p, c);
+    parent = ofd_node_parent(oft_p, parent);
+
+    p_len = ofd_getprop(oft_p, parent, "ranges", &ranges, sizeof(ranges));
+    DBG("%s: ranges\n", __func__);
+    int i; for (i=0; i<p_len; i++) {DBG("%08x ", ranges[i]);}
+    DBG("\n");
+
+    p_len = ofd_getprop(oft_p, parent, "#address-cells", &addr_c, 
sizeof(addr_c));
+    DBG("%s address is %d\n", __func__, addr_c);
+    ranges_i = addr_c;  /* skip over the child address */
+    
+    DBG("%s address is %d\n", __func__, addr_c);
+    switch (addr_c) {
+    case 1: 
+        ranges_addr = ranges[ranges_i];
+        break;
+    case 2:
+        ranges_addr = (((u64)ranges[ranges_i]) << 32) |
+                      ranges[ranges_i + 1];
+        break;
+    case 3:  /* the G5 case, how to squeeze 96 bits into 64 */
+        ranges_addr = (((u64)ranges[ranges_i+1]) << 32) |
+                      ranges[ranges_i + 2];
+        break;
+    case 4:
+        ranges_addr = (((u64)ranges[ranges_i+2]) << 32) |
+                      ranges[ranges_i + 4];
+        break;
+    default:
+        PANIC("#address-cells out of range\n");
+        break;
+    }
+    
+    DBG("%s: address 0x%lx\n", __func__, ranges_addr);
+    return ranges_addr;
+}
+
+static unsigned long find_pic_address_from_node(void *oft_p, ofdn_t c)
+{
+    unsigned long reg_addr, range_addr, addr;
+
+    /*
+     * The address is the sum of the address in the reg property of this node
+     * and the ranges property of the granparent node.
+     */
+    reg_addr = find_reg_addr_from_node(oft_p, c);
+    range_addr = find_ranges_addr_from_node(oft_p, c);
+    addr = reg_addr + range_addr;
+    DBG("%s: address 0x%lx\n", __func__, addr);
+    return addr;
+}
+
+static unsigned int find_pic_flags_from_node(void *oft_p, ofdn_t c)
+{
+    int be_len;
+    unsigned int flags = 0;
+
+    /* does it have the property big endian? */
+    be_len = ofd_getprop(oft_p, c, "big_endian", NULL, 0);
+    if (be_len >= 0) {
+        DBG("%s: Big Endian found\n", __func__);
+        flags |= MPIC_BIG_ENDIAN;
+    }
+    DBG("%s: flags 0x%x\n", __func__, flags);
+    return flags;
+}
+
+static int find_mpic_simple_probe(void *oft_p )
+{
+    u32 addr_cells;
+    int rc;
+    u32 addr[2];
+
+    rc = ofd_getprop(oft_p, OFD_ROOT, "#address-cells", &addr_cells, 
sizeof(addr_cells));
+    if ( rc < 0 ) {
+        /* if the property does not exist use its default value, 2 */
+        addr_cells = 2;
+    }
+
+    rc = ofd_getprop(oft_p, OFD_ROOT, "platform-open-pic", addr, sizeof(addr));
+    if (rc < 0) {
+        return rc;
+    }
+
+    opic_addr = addr[0];
+    if (addr_cells == 2) {
+        opic_addr <<= 32;
+        opic_addr |= addr[1];
+    }
+    DBG("%s: found OpenPIC at: 0x%lx\n", __func__, opic_addr);
+    /* we did not really find the pic device, only its address. 
+     * We use big endian by default
+     */
+    opic_flags |= MPIC_BIG_ENDIAN | MPIC_BROKEN_U3;
+    return 0;
+}
+
+static int find_mpic_canonical_probe(void *oft_p)
+{
+    ofdn_t c;
+    const char mpic_type[] = "open-pic";
+    /* some paths are special and we cannot find the address
+     * by the usual method */
+    const char *excluded_paths[] = { "/interrupt-controller" };
+
+    /*
+     * Search through the OFD tree for all devices of type 'open_pic'.
+     * We select the one without an 'interrupt' property.
+     */
+    c = ofd_node_find_by_prop(oft_p, OFD_ROOT, "device_type", mpic_type,
+                                        sizeof(mpic_type));
+    while (c > 0) {
+        int int_len;
+        int good_mpic;
+        const char * path = ofd_node_path(oft_p, c);
+
+        good_mpic = 0;
+        int_len = ofd_getprop(oft_p, c, "interrupts", NULL, 0);
+        if (int_len < 0) {
+            int i;
+
+            /* there is no property interrupt.  This could be the pic */
+            DBG("%s: potential OpenPIC in: %s\n", __func__, path);
+            good_mpic = 1;
+
+            for (i = 0; i < ARRAY_SIZE(excluded_paths) && good_mpic; i++) {
+                const char *excluded_path = excluded_paths[i];
+                if (!strncmp(path, excluded_path, strlen(excluded_path)))
+                    good_mpic = 0;
+            }
+        }
+
+        if (good_mpic) {
+            DBG("%s: found OpenPIC in: %s\n", __func__, path);
+            opic_addr = find_pic_address_from_node(oft_p, c);
+            opic_flags = find_pic_flags_from_node(oft_p, c);
+            return 0;
+        }
+
+        c = ofd_node_find_next(oft_p, c);
+    }
+
+    DBG("%s: Could not find a pic\n", __func__);
+    return -1;
+}
+
+int find_mpic(unsigned long oftree)
+{
+    void *oft_p;
+    int rc;
+
+    opic_addr = (unsigned long) -1;
+    opic_flags = 0;
+
+    oft_p = (void *) oftree;
+    rc = find_mpic_simple_probe(oft_p);
+
+    if (rc < 0) {
+        DBG("%s: Searching for pic ...\n", __func__);
+        rc = find_mpic_canonical_probe(oft_p);
+    }
+
+    return rc;
+}
+
+unsigned long get_mpic_address()
+{
+    return opic_addr;
+}
+
+unsigned int get_mpic_flags()
+{
+    return opic_flags;
+}
diff -r d16209a2476e xen/arch/ppc/find_mpic.h
--- /dev/null   Thu Jan  1 00:00:00 1970 +0000
+++ b/xen/arch/ppc/find_mpic.h  Thu May 18 10:15:31 2006 -0400
@@ -0,0 +1,8 @@
+#ifndef _FIND_MPIC_H
+#define _FIND_MPIC_H
+
+int find_mpic(unsigned long oftree);
+unsigned long get_mpic_address();
+unsigned int get_mpic_flags();
+
+#endif  /* #ifndef _FIND_MPIC_H */

_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel

<Prev in Thread] Current Thread [Next in Thread>
  • [XenPPC] [PATCH] open pic detection, Maria Butrico <=