[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, conif (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];} +#endifstatic 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]; } - -#endifextern 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", ®, 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(multibootif (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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |