[ppc64] vty updates, from Hollis Blanchard --- arch/ppc64/kernel/pSeries_lpar.c | 109 +++++++++++++++++++++++++++------------ arch/ppc64/kernel/udbg.c | 4 + include/asm-ppc64/prom.h | 1 3 files changed, 82 insertions(+), 32 deletions(-) diff -puN arch/ppc64/kernel/pSeries_lpar.c~ppc64-vty_node arch/ppc64/kernel/pSeries_lpar.c --- 25/arch/ppc64/kernel/pSeries_lpar.c~ppc64-vty_node 2004-01-13 23:21:57.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/pSeries_lpar.c 2004-01-13 23:21:57.000000000 -0800 @@ -35,6 +35,7 @@ #include #include #include +#include long plpar_pte_remove(unsigned long flags, unsigned long ptex, @@ -206,6 +207,63 @@ static unsigned char udbg_getcLP(void) } } +/* returns 0 if couldn't find or use /chosen/stdout as console */ +static int find_udbg_vterm(void) +{ + struct device_node *stdout_node; + u32 *termno; + char *name; + int found = 0; + + /* find the boot console from /chosen/stdout */ + if (!of_stdout_device) { + printk(KERN_WARNING "couldn't get path from /chosen/stdout!\n"); + return found; + } + stdout_node = of_find_node_by_path(of_stdout_device); + if (!stdout_node) { + printk(KERN_WARNING "couldn't find node from /chosen/stdout\n"); + return found; + } + + /* now we have the stdout node; figure out what type of device it is. */ + name = (char *)get_property(stdout_node, "name", 0); + if (!name) { + printk(KERN_WARNING "stdout node missing 'name' property!\n"); + goto out; + } + + if (strncmp(name, "vty", 3) == 0) { + char *compatible; + compatible = (char *)get_property(stdout_node, "compatible", 0); + if (compatible && (strncmp(compatible, "hvterm1", 7) == 0)) { + termno = (u32 *)get_property(stdout_node, "reg", 0); + if (termno) { + vtermno = termno[0]; + ppc_md.udbg_putc = udbg_putcLP; + ppc_md.udbg_getc = udbg_getcLP; + ppc_md.udbg_getc_poll = udbg_getc_pollLP; + found = 1; + } + } else { + /* XXX implement udbg_putcLP_vtty for hvterm-protocol1 case */ + printk(KERN_WARNING "%s doesn't speak hvterm1; " + "can't print udbg messages\n", of_stdout_device); + } + } else if (strncmp(name, "serial", 6)) { + /* XXX fix ISA serial console */ + printk(KERN_WARNING "serial stdout on LPAR ('%s')! " + "can't print udbg messages\n", of_stdout_device); + } else { + printk(KERN_WARNING "don't know how to print to stdout '%s'\n", + of_stdout_device); + } + +out: + of_node_put(stdout_node); + return found; +} + void pSeries_lpar_mm_init(void); /* This is called early in setup.c. @@ -213,8 +271,6 @@ void pSeries_lpar_mm_init(void); */ void pSeriesLP_init_early(void) { - struct device_node *np; - pSeries_lpar_mm_init(); ppc_md.tce_build = tce_build_pSeriesLP; @@ -225,25 +281,13 @@ void pSeriesLP_init_early(void) #endif /* The keyboard is not useful in the LPAR environment. - * Leave all the interfaces NULL. + * Leave all the ppc_md keyboard interfaces NULL. */ - /* lookup the first virtual terminal number in case we don't have a - * com port. Zero is probably correct in case someone calls udbg - * before the init. The property is a pair of numbers. The first - * is the starting termno (the one we use) and the second is the - * number of terminals. - */ - np = of_find_node_by_path("/rtas"); - if (np) { - u32 *termno = (u32 *)get_property(np, "ibm,termno", 0); - if (termno) - vtermno = termno[0]; - of_node_put(np); - } - ppc_md.udbg_putc = udbg_putcLP; - ppc_md.udbg_getc = udbg_getcLP; - ppc_md.udbg_getc_poll = udbg_getc_pollLP; + if (0 == find_udbg_vterm()) { + printk(KERN_WARNING + "can't use stdout; can't print early debug messages.\n"); + } } int hvc_get_chars(int index, char *buf, int count) @@ -286,25 +330,28 @@ int hvc_put_chars(int index, const char return -1; } +/* return the number of client vterms present */ +/* XXX this requires an interface change to handle multiple discontiguous + * vterms */ int hvc_count(int *start_termno) { u32 *termno; - struct device_node *dn; - int ret = 0; + struct device_node *vty; - if ((dn = of_find_node_by_path("/rtas")) != NULL) { - if ((termno = (u32 *)get_property(dn, "ibm,termno", 0)) != NULL) { - if (start_termno) - *start_termno = termno[0]; - ret = termno[1]; + /* consider only the first vty node. + * we should _always_ be able to find one. */ + vty = of_find_node_by_name(NULL, "vty"); + if (vty) { + if ((termno = (u32 *)get_property(vty, "reg", 0)) != NULL) { + *start_termno = *termno; } - of_node_put(dn); + of_node_put(vty); + return 1; /* we can't support >1 with this interface */ } - return ret; -} - - + /* couldn't find any vterms */ + return 0; +} long pSeries_lpar_hpte_insert(unsigned long hpte_group, unsigned long va, unsigned long prpn, diff -puN include/asm-ppc64/prom.h~ppc64-vty_node include/asm-ppc64/prom.h --- 25/include/asm-ppc64/prom.h~ppc64-vty_node 2004-01-13 23:21:57.000000000 -0800 +++ 25-akpm/include/asm-ppc64/prom.h 2004-01-13 23:21:57.000000000 -0800 @@ -169,6 +169,7 @@ struct prom_t { }; extern struct prom_t prom; +extern char *of_stdout_device; extern int boot_cpuid; diff -puN arch/ppc64/kernel/udbg.c~ppc64-vty_node arch/ppc64/kernel/udbg.c --- 25/arch/ppc64/kernel/udbg.c~ppc64-vty_node 2004-01-13 23:21:57.000000000 -0800 +++ 25-akpm/arch/ppc64/kernel/udbg.c 2004-01-13 23:21:57.000000000 -0800 @@ -127,8 +127,10 @@ udbg_write(const char *s, int n) { int remain = n; char c; + if (!ppc_md.udbg_putc) - for (;;); /* stop here for cpuctl */ + return 0; + if ( s && *s != '\0' ) { while ( (( c = *s++ ) != '\0') && (remain-- > 0)) { ppc_md.udbg_putc(c); _