[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 <asm/tlbflush.h>
 #include <asm/tlb.h>
 #include <asm/hvcall.h>
+#include <asm/prom.h>
 
 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);

_