[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[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


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.