patch-2.3.43 linux/arch/ppc/xmon/start.c

Next file: linux/arch/ppc/xmon/xmon.c
Previous file: linux/arch/ppc/mm/init.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.3.42/linux/arch/ppc/xmon/start.c linux/arch/ppc/xmon/start.c
@@ -8,19 +8,34 @@
 #include <asm/page.h>
 #include <linux/adb.h>
 #include <linux/pmu.h>
+#include <linux/kernel.h>
 #include <asm/prom.h>
 #include <asm/bootx.h>
+#include <asm/feature.h>
 #include <asm/processor.h>
 
 static volatile unsigned char *sccc, *sccd;
 unsigned long TXRDY, RXRDY;
 extern void xmon_printf(const char *fmt, ...);
-extern void map_bootx_text(void);
 extern void drawchar(char);
 extern void drawstring(const char *str);
+static int xmon_expect(const char *str, unsigned int timeout);
 
 static int console = 0;
 static int use_screen = 0;
+static int via_modem = 0;
+static int xmon_use_sccb = 0;
+static struct device_node *macio_node;
+
+#define TB_SPEED	25000000
+
+static inline unsigned int readtb(void)
+{
+	unsigned int ret;
+
+	asm volatile("mftb %0" : "=r" (ret) :);
+	return ret;
+}
 
 void buf_access(void)
 {
@@ -36,17 +51,19 @@
 	if ( _machine == _MACH_Pmac )
 	{
 		struct device_node *np;
-		extern boot_infos_t *boot_infos;
 		unsigned long addr;
-
 #ifdef CONFIG_BOOTX_TEXT
-		if (boot_infos != 0 && find_via_pmu()) {
-			printk("xmon uses screen and keyboard\n");
+		extern boot_infos_t *disp_bi;
+
+		/* needs to be hacked if xmon_printk is to be used
+ 		   from within find_via_pmu() */
+		if (!via_modem && disp_bi && find_via_pmu()) {
+			drawstring("xmon uses screen and keyboard\n");
 			use_screen = 1;
-			map_bootx_text();
 			return;
 		}
 #endif
+
 #ifdef CHRP_ESCC
 		addr = 0xc1013020;
 #else
@@ -57,9 +74,10 @@
 		
 		np = find_devices("mac-io");
 		if (np && np->n_addrs) {
+			macio_node = np;
 			addr = np->addrs[0].address + 0x13000;
-			/* use the B channel on the iMac, A channel on others */
-			if (addr >= 0xf0000000)
+			/* use the B channel on the iMac */
+			if (!xmon_use_sccb)
 				addr += 0x20; /* use A channel */
 		}
 		base = (volatile unsigned char *) ioremap(addr & PAGE_MASK, PAGE_SIZE);
@@ -70,22 +88,22 @@
 		sccd = sccc + (0xf3013030 - 0xf3013020);
 #endif
 	}
-	else if ( _machine & _MACH_chrp )
+	else if ( _machine & _MACH_gemini )
 	{
 		/* should already be mapped by the kernel boot */
-		sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
-		sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
+		sccc = (volatile unsigned char *) 0xffeffb0d;
+		sccd = (volatile unsigned char *) 0xffeffb08;
 		TXRDY = 0x20;
 		RXRDY = 1;
+		console = 1;
 	}
-	else if ( _machine & _MACH_gemini )
+	else
 	{
 		/* should already be mapped by the kernel boot */
-		sccc = (volatile unsigned char *) 0xffeffb0d;
-		sccd = (volatile unsigned char *) 0xffeffb08;
+		sccc = (volatile unsigned char *) (isa_io_base + 0x3fd);
+		sccd = (volatile unsigned char *) (isa_io_base + 0x3f8);
 		TXRDY = 0x20;
 		RXRDY = 1;
-		console = 1;
 	}
 }
 
@@ -98,7 +116,7 @@
 xmon_write(void *handle, void *ptr, int nb)
 {
     char *p = ptr;
-    int i, ct;
+    int i, c, ct;
 
 #ifdef CONFIG_BOOTX_TEXT
     if (use_screen) {
@@ -111,20 +129,26 @@
     if (!scc_initialized)
 	xmon_init_scc();
     for (i = 0; i < nb; ++i) {
-#ifdef CONFIG_ADB	    
+    ct = 0;
 	while ((*sccc & TXRDY) == 0)
+#ifdef CONFIG_ADB	    
 	    if (sys_ctrler == SYS_CTRLER_PMU)
 		pmu_poll();
+#else
+		;
 #endif /* CONFIG_ADB */
-	buf_access();
-	if ( console && (*p != '\r'))
-		printk("%c", *p);
-	ct = 0;
-	if ( *p == '\n')
+	c = p[i];
+	if (c == '\n' && !ct) {
+	    c = '\r';
 		ct = 1;
-	*sccd = *p++;
-	if ( ct )
-		xmon_write(handle, "\r", 1);
+	    --i;
+	} else {
+	    if (console)
+		printk("%c", c);
+	    ct = 0;
+	}
+	buf_access();
+	*sccd = c;
     }
     return i;
 }
@@ -206,36 +230,49 @@
     if (!scc_initialized)
 	xmon_init_scc();
     for (i = 0; i < nb; ++i) {
-#ifdef CONFIG_ADB	    
 	while ((*sccc & RXRDY) == 0)
+#ifdef CONFIG_ADB	    
 	    if (sys_ctrler == SYS_CTRLER_PMU)
 		pmu_poll();
+#else
+		;
 #endif /* CONFIG_ADB */
 	buf_access();
-#if 0	
-	if ( 0/*console*/ )
-		*p++ = ppc_md.kbd_getkeycode();
-	else
-#endif		
 		*p++ = *sccd;
     }
     return i;
 }
 
+int
+xmon_read_poll(void)
+{
+	if ((*sccc & RXRDY) == 0) {
+#ifdef CONFIG_ADB	    
+		if (sys_ctrler == SYS_CTRLER_PMU)
+			pmu_poll();
+#else
+			;
+#endif			
+		return -1;
+	}
+	buf_access();
+	return *sccd;
+}
+
 static unsigned char scc_inittab[] = {
     13, 0,		/* set baud rate divisor */
     12, 1,
     14, 1,		/* baud rate gen enable, src=rtxc */
     11, 0x50,		/* clocks = br gen */
-    5,  0x6a,		/* tx 8 bits, assert RTS */
-    4,  0x44,		/* x16 clock, 1 stop */
+    5,  0xea,		/* tx 8 bits, assert DTR & RTS */
+    4,  0x46,		/* x16 clock, 1 stop */
     3,  0xc1,		/* rx enable, 8 bits */
 };
 
 void
 xmon_init_scc()
 {
-	if ( _machine & (_MACH_chrp|_MACH_gemini) )
+	if ( _machine == _MACH_chrp )
 	{
 		sccd[3] = 0x83; eieio();	/* LCR = 8N1 + DLAB */
 		sccd[0] = 3; eieio();		/* DLL = 38400 baud */
@@ -248,6 +285,14 @@
 	{
 		int i, x;
 
+		if (macio_node != 0) {
+			unsigned int t0;
+
+			feature_set(macio_node, FEATURE_Modem_power);
+			t0 = readtb();
+			while (readtb() - t0 < 3*TB_SPEED)
+				eieio();
+		}
 		for (i = 20000; i != 0; --i) {
 			x = *sccc; eieio();
 		}
@@ -259,6 +304,18 @@
 		}
 	}
 	scc_initialized = 1;
+	if (via_modem) {
+		for (;;) {
+			xmon_write(0, "ATE1V1\r", 7);
+			if (xmon_expect("OK", 5)) {
+				xmon_write(0, "ATA\r", 4);
+				if (xmon_expect("CONNECT", 40))
+					break;
+			}
+			xmon_write(0, "+++", 3);
+			xmon_expect("OK", 3);
+		}
+	}
 }
 
 #if 0
@@ -330,6 +387,35 @@
 static char line[256];
 static char *lineptr;
 static int lineleft;
+
+int xmon_expect(const char *str, unsigned int timeout)
+{
+	int c;
+	unsigned int t0;
+
+	timeout *= TB_SPEED;
+	t0 = readtb();
+	do {
+		lineptr = line;
+		for (;;) {
+			c = xmon_read_poll();
+			if (c == -1) {
+				if (readtb() - t0 > timeout) {
+					printk("timeout\n");
+					return 0;
+				}
+				continue;
+			}
+			if (c == '\n')
+				break;
+			printk("%c", c);
+			if (c != '\r' && lineptr < &line[sizeof(line) - 1])
+				*lineptr++ = c;
+		}
+		*lineptr = 0;
+	} while (strstr(line, str) == NULL);
+	return 1;
+}
 
 int
 xmon_getchar(void)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)