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

Re: [XenPPC] [Patch] Find serial device and platform type



This patch is intended as a preliminary request for comment, status update and a good place to keep it, in case I destroy my tree. It's work in progress.

(I don't get my email to echo back to me for quite a few hours, btw, so commnts like this one might not be too timely.)

Maria Butrico wrote:
diff -r 56e1802303e5 xen/arch/ppc/boot_of.c
--- a/xen/arch/ppc/boot_of.c    Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/arch/ppc/boot_of.c    Fri Apr 21 10:41:42 2006 -0400
@@ -24,6 +24,36 @@
 #include <xen/compile.h>
 #include <public/of-devtree.h>
 #include <asm/page.h>
+#include <xen/string.h>
+
+struct global_hardware_stuff {
+    int platform_type;
+    #define UNKNOWN_PLATFORM        1
+    #define PMAC_HARDWARE           2
+    #define MAPLE_SIM               3
+    #define MAPLE_HARDWARE          4
+    #define JS2X_HARDWARE           5
+
+    /* these are not definite platform but we start to isolate the type */
+    #define MAPLE_GENERIC           10  /* could be simulator(MAPLE_SIM) or
+                                           hardware(MAPLE_HARDWARE) or JX20 */
+
+    int hv_supported;
+
+    struct {
+        int type;
+        #define UART_UNKNOWN    0
+        #define UART_ZILOG      2
+        #define UART_NS16550    3
+
+        u64 uart_io_base;
+        u64 isa_io_base;
+        u32 clock;
+        // function serial port initialization routine
+    } serial_port;
+};
+static struct global_hardware_stuff global_hs;
+extern int opt_nohv;
static ulong of_vec;
 static ulong of_msr;
@@ -152,6 +182,7 @@ static int __init of_getprop(int ph, con
if (rets[0] == OF_FAILURE) {
         DBG("getprop 0x%x %s -> FAILURE\n", ph, name);
+        if (buflen > 0) memset(buf, 0, 1);
         return OF_FAILURE;
     }
@@ -301,6 +332,7 @@ static int __init of_instance_to_package return rets[0];
 }
+#endif
static int __init of_getparent(int ph)
 {
@@ -311,8 +343,6 @@ static int __init of_getparent(int ph)
     DBG("getparent 0x%x -> 0x%x\n", ph, rets[0]);
     return rets[0];
 }
-
-#endif
extern char _start[];
 extern char _end[];
@@ -331,7 +361,6 @@ static void boot_of_probemem(multiboot_i
     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));
     of_getprop(root, "#size-cells", &size_cells, sizeof (size_cells));
     DBG("%s: address_cells=%d  size_cells=%d\n",
@@ -786,10 +815,282 @@ static void boot_of_module(ulong r3, ulo
 }
-int __init boot_of_serial(void)
-{
-    /* right now we are punting and using mambo writes which is the
-     * hardcoded setup */
+static void search_by_property_value(int p, const char *prop_name,
+                const char *prop_value)
+{
+    int pnext;          /* of handdle */
+
+    do {
+ // does this package have the property 'prop_name' with + // value "prop_value"?
+        char of_property[256];
+        of_property[0] = '\0';
+        of_getprop(p, prop_name, of_property, sizeof (of_property));
+        if (strncmp(of_property, prop_value, sizeof (prop_value)) == 0) {
+            char path[256];
+            int sz = of_package_to_path(p, path, sizeof(path));
+            of_printf("\npackage with property '%s' with value '%s' found. "
+                            "path is %s (size %d)\n", prop_name, prop_value,
+                            path, sz);
+#ifdef OF_DEBUG
+            // Print all its properties
+            char name[128];
+            int result = of_nextprop(p, 0, name);       /* first prop. */
+            while (result > 0) {
+                int sz;
+                u64 obj[1024];
+                sz = of_getproplen(p, name);
+                if (sz > 0) {
+                    int actual = of_getprop(p, name, obj, sz);
+                    of_printf("device property *%s* size %d value %s  ",
+                                        name, actual, (char*)obj);
+                    int i;
+                    for (i=0; i<=(actual/sizeof(obj[0])); i++)
+                                of_printf("0x%016lx ", obj[i]);
+                    of_printf("\n");
+                } else if (0 == sz) {
+                        of_printf("device property *%s* size 0\n",
+                                        name);
+                }
+
+                result = of_nextprop(p, name, name);
+            }
+#endif
+        }
+
+        /* do children first */
+        pnext = of_getchild(p);
+        if (pnext != 0) {
+            search_by_property_value(pnext, prop_name, prop_value);
+        }
+
+        p = of_getpeer(p);
+    } while (p != OF_FAILURE && p != 0);
+}
+
+
+/*
+ * Returns the value of the property '/#size-cells'
+ */
+int __init boot_of_get_sizecells_prop()
+{
+    int of_root;
+    u32 cell = 1;
+ + of_root = of_finddevice("/");
+    if (OF_FAILURE != of_root)
+        of_getprop(of_root, "#size-cells", &cell, sizeof(cell));
+    return cell;
+}
+
+int __init boot_of_serial()
+{
+    int p, ofout;      /* of handle */
+    int rc;
+    char of_property[256];
+    char ofout_path[256] = {0,};
+    const char serial[] = "serial";
+    const char macio[] = "mac-io";
+    const char escc[] = "escc";
+
+    #ifdef OF_DEBUG
+    {
+    p = of_finddevice("/");
+    const char device_type[] = "device_type";
+    search_by_property_value(p, device_type, serial);
+    }
+    #endif
+
+    global_hs.serial_port.type = UART_UNKNOWN;
+
+    /* copied and adapted from rhype */
+    ofout = OF_FAILURE;
+
+    /* probe /options tree */
+    rc = p = of_finddevice("/options");
+    if (p != OF_FAILURE) {
+        rc = of_getprop(p, "output-device", ofout_path, sizeof(ofout_path));
+ } + if (OF_FAILURE == rc) {
+        strncpy(ofout_path, serial, sizeof(serial));
+    }
+
+    /*
+     * if the options are not a path (they do not start with '/')
+     * then they are aliases and we must look them up.  we look it
+     * up in aliases because it is possible that the OF does not
+     * support finddevice() of an alias.
+     */
+    if (ofout_path[0] != '/') {
+        p = of_finddevice("/aliases");
+        if (p != OF_FAILURE) {
+            char alias[256];
+            memcpy(alias, ofout_path, sizeof(alias));
+            rc = of_getprop(p, alias, ofout_path, sizeof (ofout_path));
+        }
+    }
+
+    if (OF_FAILURE != rc) {
+        ofout = of_finddevice(ofout_path);
+    } else {
+        s32 iout;       /* ihandle ?? */
+        /*
+         * Our last chance is to figure out the package for
+         * the current console and hopefully discover it to be
+         * a serial device.
+         */
+        p = of_finddevice("/chosen");
+        if (p != OF_FAILURE) {
+            rc = of_getprop(p, "stdout", &iout, sizeof(iout));
+        }
+        if (rc != OF_FAILURE) {
+            rc = of_instance_to_path(iout, ofout_path, sizeof(ofout_path));
+ if (rc != OF_FAILURE) + ofout = of_finddevice(ofout_path);
+        }
+    }
+
+    DBG("serial port OF handle=0x%x\n", ofout);
+
+    if (OF_FAILURE == ofout) {
+        /* can try the rtas device.  Code not written yet */
+        of_printf("Could not find any serial device\n");
+        return OF_FAILURE;
+    }
+
+
+    /* Now we have the OF handle of the serial device.  Let's find out
+     * what it is and its address.
+     *
+     * The device must have of type 'serial'
+     *
+     * If the grandparent directory has the name 'mac-io', then this must
+     * be a power mac.  The serial device is a zilog.
+     *
+     * Otherwise (we are assuming that) the grandparent has the name
+     * 'pci' and the parent 'isa'.  The serial device is a NS16550.
+     *
+     * And what about the ns16750?
+ * + */
+    rc = of_getprop(ofout, "device_type", of_property, sizeof(of_property));
+    of_printf("serial device type %s\n", of_property);
+
+    union of_pci_hi {
+       u32 word;
+       struct {
+           u32  opa_n: 1; /* relocatable */
+           u32  opa_p: 1; /* prefetchable */
+           u32  opa_t: 1; /* aliased */
+           u32  _opa_res: 3;
+           u32  opa_s: 2; /* space code */
+           u32  opa_b: 8; /* bus number */
+           u32  opa_d: 5; /* device number */
+           u32  opa_f: 3; /* function number */
+           u32  opa_r: 8; /* register number */
+       } bits;
+    };
+    struct of_pci_addr_s {
+        union of_pci_hi opa_hi;
+        u32 opa_mid;
+        u32 opa_lo;
+    };
+
+    if (strncmp(of_property, serial, sizeof(serial))) {
+        of_printf("Serial device is not serial\n");
+        return OF_FAILURE;
+    }
+
+    int parent, grandparent;        /* of handles */
+    parent = of_getparent(ofout);
+    if (OF_FAILURE == parent) return OF_FAILURE;
+    grandparent = of_getparent(parent);
+    if (OF_FAILURE == grandparent) return OF_FAILURE;
+
+    of_getprop(grandparent, "name", of_property, sizeof(of_property));
+    if (0 == strncmp(of_property, macio, sizeof(macio))) {
+        struct reg_property32 {
+            u32 address;
+            u32 size;
+        } reg;
+        struct of_pci_range32_s {
+            struct of_pci_addr_s opr_addr;
+            u32 opr_phys;
+            u32 opr_size;
+        } r32;
+
+        of_getprop(parent, "device_type", of_property, sizeof(of_property));
+        if (strncmp(of_property, escc, sizeof(escc))) {
+            of_printf("Serial device parent's type is not escc\n");
+            return OF_FAILURE;
+        }
+
+        if (global_hs.platform_type != PMAC_HARDWARE) {
+           of_printf("WARNING: serial device found in path mac-io"
+                     "but we don't think this is a power mac\n");
+           return OF_FAILURE;
+        }
+
+        global_hs.serial_port.type = UART_ZILOG;
+        of_getprop(grandparent , "ranges", &r32, sizeof(r32));
+        of_getprop(ofout, "reg", &reg, sizeof(reg));
+
+        of_printf("reg property address=0x%08x  size=0x%08x\n",
+                        reg.address, reg.size);
+        of_printf("ranges property %x:%x:%x %x %x\n",
+                            r32.opr_addr.opa_hi.word,
+                            r32.opr_addr.opa_mid,
+                            r32.opr_addr.opa_lo,
+                            r32.opr_phys, r32.opr_size);
+
+        global_hs.serial_port.uart_io_base = reg.address;
+        global_hs.serial_port.isa_io_base = r32.opr_phys;
+        /* io_addr = isa_io_base + uart_io_base; */
+    } else {
+        /* grandparent directory is not 'mac-io'.  We are assuming 'pci/isa' */
+        struct isa_reg_property {
+            u32 space;
+            u32 address;
+            u32 size;
+        } isa_reg;
+        struct of_pci_range64_s {
+            struct of_pci_addr_s opr_addr;
+            u32 opr_phys_hi;
+            u32 opr_phys_lo;
+            u32 opr_size_hi;
+            u32 opr_size_lo;
+        } r64;
+        u32 clock;
+
+        global_hs.serial_port.type = UART_NS16550;
+        of_getprop(grandparent , "ranges", &r64, sizeof(r64));
+        of_getprop(ofout, "clock-frequency", &clock, sizeof (clock));
+        of_getprop(ofout, "reg", &isa_reg, sizeof(isa_reg));
+
+        of_printf("reg property address=0x%08x  size=0x%08x\n",
+                        isa_reg.address, isa_reg.size);
+        of_printf("ranges property %x:%x:%x %x:%x %x:%x\n",
+                     r64.opr_addr.opa_hi.word,
+                     r64.opr_addr.opa_mid,
+                     r64.opr_addr.opa_lo,
+                     r64.opr_phys_hi,
+                     r64.opr_phys_lo,
+                     r64.opr_size_hi, r64.opr_size_lo);
+
+        global_hs.serial_port.uart_io_base = isa_reg.address;
+ global_hs.serial_port.isa_io_base = + (((u64)r64.opr_phys_hi) << 32) | r64.opr_phys_lo;
+        global_hs.serial_port.clock = clock;
+        /* io_addr = isa_io_base + uart_io_base; */
+    }
+
+    of_printf("%s: serial type=%d  io base=0x%016lx  isa io@=0x%016lx  "
+              "clock=%d\n",
+              __func__, global_hs.serial_port.type,
+              global_hs.serial_port.uart_io_base,
+              global_hs.serial_port.isa_io_base,
+              global_hs.serial_port.clock
+              );
return 1;
 }
@@ -825,6 +1126,119 @@ int __init boot_of_rtas(void)
     return 1;
 }
+/*
+ * Returns the length of the OF compatible property; OF_FAILURE on error
+ * The value of the property itself is returned in the first parameter.
+ */
+int __init boot_of_get_compatible_prop(char *cstring, int cstring_size)
+{
+    int of_root;
+    int comp_length;
+ + of_root = of_finddevice("/");
+    if (OF_FAILURE == of_root) return OF_FAILURE;
+
+    comp_length = of_getprop(of_root, "compatible", cstring, cstring_size);
+    #if 0
+    if (comp_length != OF_FAILURE) {
+        // null separated string yuck
+        int used_length;
+        of_printf("%s :\n", __func__);
+        for (used_length = 0; used_length < comp_length; used_length++) {
+            if (cstring[used_length] == '\0' ) {
+                of_printf("   NULL\n");
+            } else {
+                of_printf("%c", cstring[used_length]);
+            }
+        }
+ } + #endif
+
+    return comp_length;
+}
+
+/*
+ * Does the compatible of property indicate that the platform is a Power
+ * Macintosh, or a maple (hardware or simulated), or ..
+ * return 0 if not an known value;
+ */
+int __init boot_of_platform(char * compatible_p, int c_length)
+{
+    static const char pmac_string[] = "Power Macintosh";
+    static const char maple_string[] = "Momentum,Maple";
+    static const char JS_20[] = "junk";
+
+    char *cmpstr;
+    int used_length;
+
+    // loop over each null terminated piece of the compatible property
+    for (cmpstr = compatible_p, used_length = 0; used_length < c_length;
+         cmpstr = &compatible_p[used_length]) {
+        if (strstr(cmpstr, pmac_string)) return PMAC_HARDWARE;
+        if (strstr(cmpstr, maple_string)) return MAPLE_GENERIC;
+        if (strstr(cmpstr, JS_20)) return JS2X_HARDWARE;
+        used_length += strlen(cmpstr) + 1;
+    }
+
+    return 0;
+}
+
+void __init boot_of_hardware_specific() +{
+    int rc;
+    char compatible_string[256];
+    int compatible_length;
+    int cell;
+
+    memset(&global_hs, 0, sizeof(global_hs));
+    global_hs.platform_type = UNKNOWN_PLATFORM;
+
+    compatible_length = boot_of_get_compatible_prop(compatible_string,
+                                               sizeof(compatible_string));
+
+    if (compatible_length != OF_FAILURE) {
+        rc = boot_of_platform(compatible_string, compatible_length);
+        cell = boot_of_get_sizecells_prop();
+        switch (rc) {
+        default:
+            of_printf("Warning: %s is not aware of this machine type %d\n",
+                            __func__, rc);
+            break;
+ + case 0:
+            // did not learn anything
+            break;
+
+        case PMAC_HARDWARE:
+            global_hs.platform_type = rc;
+            if (cell != 1) of_panic("powermac with cell %d\n", cell);
+
+            /*
+             * Power Macintosh' do not distinguish between supervisor and
+             * hypervisor mode.  Hence, we run, if at all, with in a special
+             * mode called non-hypervisor hypervisor. (nohv)
+             */
+            of_printf("Non hypervisor hardware found.\n");
+            global_hs.hv_supported = 0;
+            opt_nohv = 1;
+            break;
+
+        case MAPLE_GENERIC:
+            global_hs.platform_type = rc;
+            if (cell != 2) of_panic("maple like thing with cell %d\n", cell);
+            global_hs.hv_supported = 1;
+            break;
+        }
+    }
+
+    of_printf("%s: type=%d  hv=%d\n", __func__, global_hs.platform_type,
+                    global_hs.hv_supported);
+
+    boot_of_serial();
+    boot_of_rtas();
+}
+
+
 multiboot_info_t __init *boot_of_init(
         ulong r3, ulong r4, ulong vec, ulong r6, ulong r7, ulong orig_msr)
 {
@@ -858,9 +1272,16 @@ multiboot_info_t __init *boot_of_init(
     boot_of_probemem(&mbi);
     boot_of_bootargs(&mbi);
     boot_of_module(r3, r4, &mbi);
-    boot_of_serial();
     boot_of_cpus();
-    boot_of_rtas();
+
+    /* Note: serial and rtas were before cpus, but should really happen after 
hardware
+     * specific, since we want to use the machine type as a hint of where/what
+     * the serial device might be
+     *
+     * If serial initalization needs to be before cpus, then we need to move up
+     * hardware specific as well.
+     */
+    boot_of_hardware_specific();
/* end of OF */
     of_printf("closing OF stdout...\n");
diff -r 56e1802303e5 xen/arch/ppc/setup.c
--- a/xen/arch/ppc/setup.c      Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/arch/ppc/setup.c      Fri Apr 21 10:41:42 2006 -0400
@@ -43,6 +43,12 @@ int opt_noht = 0;
 int opt_noht = 0;
 boolean_param("noht", opt_noht);
+/* opt_nohv: If true, hardware has no hypervisor (HV) mode or nohv boot + * parameter was specified. + */
+int opt_nohv = 0;
+boolean_param("nohv", opt_nohv);
+
 int opt_earlygdb = 0;
 boolean_param("earlygdb", opt_earlygdb);
@@ -282,6 +288,8 @@ static void __init __start_xen(multiboot
     if (dom0 == NULL)
         panic("Error creating domain 0\n");
     set_bit(_DOMF_privileged, &dom0->domain_flags);
+    if (opt_nohv)
+       set_bit(_DOMF_prob, &dom0->domain_flags);
/* Grab the DOM0 command line. Skip past the image name. */
     cmdline = (char *)(mod[0].string ? __va((ulong)mod[0].string) : NULL);
diff -r 56e1802303e5 xen/include/xen/sched.h
--- a/xen/include/xen/sched.h   Wed Apr 12 15:41:55 2006 -0500
+++ b/xen/include/xen/sched.h   Fri Apr 21 10:41:42 2006 -0400
@@ -392,6 +392,10 @@ extern struct domain *domain_list;
  /* Domain is being debugged by controller software. */
 #define _DOMF_debugging        4
 #define DOMF_debugging         (1UL<<_DOMF_debugging)
+ /* run domain in prob mode */
+#define _DOMF_prob      7
+#define DOMF_prob       (1UL<<_DOMF_prob)
+
static inline int vcpu_runnable(struct vcpu *v)
 {

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



_______________________________________________
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®.