xref: /OK3568_Linux_fs/kernel/arch/powerpc/xmon/nonstdio.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0-or-later
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * Copyright (C) 1996-2005 Paul Mackerras.
4*4882a593Smuzhiyun  */
5*4882a593Smuzhiyun #include <linux/string.h>
6*4882a593Smuzhiyun #include <asm/udbg.h>
7*4882a593Smuzhiyun #include <asm/time.h>
8*4882a593Smuzhiyun #include "nonstdio.h"
9*4882a593Smuzhiyun 
10*4882a593Smuzhiyun static bool paginating, paginate_skipping;
11*4882a593Smuzhiyun static unsigned long paginate_lpp; /* Lines Per Page */
12*4882a593Smuzhiyun static unsigned long paginate_pos;
13*4882a593Smuzhiyun 
xmon_start_pagination(void)14*4882a593Smuzhiyun void xmon_start_pagination(void)
15*4882a593Smuzhiyun {
16*4882a593Smuzhiyun 	paginating = true;
17*4882a593Smuzhiyun 	paginate_skipping = false;
18*4882a593Smuzhiyun 	paginate_pos = 0;
19*4882a593Smuzhiyun }
20*4882a593Smuzhiyun 
xmon_end_pagination(void)21*4882a593Smuzhiyun void xmon_end_pagination(void)
22*4882a593Smuzhiyun {
23*4882a593Smuzhiyun 	paginating = false;
24*4882a593Smuzhiyun }
25*4882a593Smuzhiyun 
xmon_set_pagination_lpp(unsigned long lpp)26*4882a593Smuzhiyun void xmon_set_pagination_lpp(unsigned long lpp)
27*4882a593Smuzhiyun {
28*4882a593Smuzhiyun 	paginate_lpp = lpp;
29*4882a593Smuzhiyun }
30*4882a593Smuzhiyun 
xmon_readchar(void)31*4882a593Smuzhiyun static int xmon_readchar(void)
32*4882a593Smuzhiyun {
33*4882a593Smuzhiyun 	if (udbg_getc)
34*4882a593Smuzhiyun 		return udbg_getc();
35*4882a593Smuzhiyun 	return -1;
36*4882a593Smuzhiyun }
37*4882a593Smuzhiyun 
xmon_write(const char * ptr,int nb)38*4882a593Smuzhiyun static int xmon_write(const char *ptr, int nb)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	int rv = 0;
41*4882a593Smuzhiyun 	const char *p = ptr, *q;
42*4882a593Smuzhiyun 	const char msg[] = "[Hit a key (a:all, q:truncate, any:next page)]";
43*4882a593Smuzhiyun 
44*4882a593Smuzhiyun 	if (nb <= 0)
45*4882a593Smuzhiyun 		return rv;
46*4882a593Smuzhiyun 
47*4882a593Smuzhiyun 	if (paginating && paginate_skipping)
48*4882a593Smuzhiyun 		return nb;
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun 	if (paginate_lpp) {
51*4882a593Smuzhiyun 		while (paginating && (q = strchr(p, '\n'))) {
52*4882a593Smuzhiyun 			rv += udbg_write(p, q - p + 1);
53*4882a593Smuzhiyun 			p = q + 1;
54*4882a593Smuzhiyun 			paginate_pos++;
55*4882a593Smuzhiyun 
56*4882a593Smuzhiyun 			if (paginate_pos >= paginate_lpp) {
57*4882a593Smuzhiyun 				udbg_write(msg, strlen(msg));
58*4882a593Smuzhiyun 
59*4882a593Smuzhiyun 				switch (xmon_readchar()) {
60*4882a593Smuzhiyun 				case 'a':
61*4882a593Smuzhiyun 					paginating = false;
62*4882a593Smuzhiyun 					break;
63*4882a593Smuzhiyun 				case 'q':
64*4882a593Smuzhiyun 					paginate_skipping = true;
65*4882a593Smuzhiyun 					break;
66*4882a593Smuzhiyun 				default:
67*4882a593Smuzhiyun 					/* nothing */
68*4882a593Smuzhiyun 					break;
69*4882a593Smuzhiyun 				}
70*4882a593Smuzhiyun 
71*4882a593Smuzhiyun 				paginate_pos = 0;
72*4882a593Smuzhiyun 				udbg_write("\r\n", 2);
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun 				if (paginate_skipping)
75*4882a593Smuzhiyun 					return nb;
76*4882a593Smuzhiyun 			}
77*4882a593Smuzhiyun 		}
78*4882a593Smuzhiyun 	}
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	return rv + udbg_write(p, nb - (p - ptr));
81*4882a593Smuzhiyun }
82*4882a593Smuzhiyun 
xmon_putchar(int c)83*4882a593Smuzhiyun int xmon_putchar(int c)
84*4882a593Smuzhiyun {
85*4882a593Smuzhiyun 	char ch = c;
86*4882a593Smuzhiyun 
87*4882a593Smuzhiyun 	if (c == '\n')
88*4882a593Smuzhiyun 		xmon_putchar('\r');
89*4882a593Smuzhiyun 	return xmon_write(&ch, 1) == 1? c: -1;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun 
92*4882a593Smuzhiyun static char line[256];
93*4882a593Smuzhiyun static char *lineptr;
94*4882a593Smuzhiyun static int lineleft;
95*4882a593Smuzhiyun 
xmon_getchar(void)96*4882a593Smuzhiyun static int xmon_getchar(void)
97*4882a593Smuzhiyun {
98*4882a593Smuzhiyun 	int c;
99*4882a593Smuzhiyun 
100*4882a593Smuzhiyun 	if (lineleft == 0) {
101*4882a593Smuzhiyun 		lineptr = line;
102*4882a593Smuzhiyun 		for (;;) {
103*4882a593Smuzhiyun 			c = xmon_readchar();
104*4882a593Smuzhiyun 			if (c == -1 || c == 4)
105*4882a593Smuzhiyun 				break;
106*4882a593Smuzhiyun 			if (c == '\r' || c == '\n') {
107*4882a593Smuzhiyun 				*lineptr++ = '\n';
108*4882a593Smuzhiyun 				xmon_putchar('\n');
109*4882a593Smuzhiyun 				break;
110*4882a593Smuzhiyun 			}
111*4882a593Smuzhiyun 			switch (c) {
112*4882a593Smuzhiyun 			case 0177:
113*4882a593Smuzhiyun 			case '\b':
114*4882a593Smuzhiyun 				if (lineptr > line) {
115*4882a593Smuzhiyun 					xmon_putchar('\b');
116*4882a593Smuzhiyun 					xmon_putchar(' ');
117*4882a593Smuzhiyun 					xmon_putchar('\b');
118*4882a593Smuzhiyun 					--lineptr;
119*4882a593Smuzhiyun 				}
120*4882a593Smuzhiyun 				break;
121*4882a593Smuzhiyun 			case 'U' & 0x1F:
122*4882a593Smuzhiyun 				while (lineptr > line) {
123*4882a593Smuzhiyun 					xmon_putchar('\b');
124*4882a593Smuzhiyun 					xmon_putchar(' ');
125*4882a593Smuzhiyun 					xmon_putchar('\b');
126*4882a593Smuzhiyun 					--lineptr;
127*4882a593Smuzhiyun 				}
128*4882a593Smuzhiyun 				break;
129*4882a593Smuzhiyun 			default:
130*4882a593Smuzhiyun 				if (lineptr >= &line[sizeof(line) - 1])
131*4882a593Smuzhiyun 					xmon_putchar('\a');
132*4882a593Smuzhiyun 				else {
133*4882a593Smuzhiyun 					xmon_putchar(c);
134*4882a593Smuzhiyun 					*lineptr++ = c;
135*4882a593Smuzhiyun 				}
136*4882a593Smuzhiyun 			}
137*4882a593Smuzhiyun 		}
138*4882a593Smuzhiyun 		lineleft = lineptr - line;
139*4882a593Smuzhiyun 		lineptr = line;
140*4882a593Smuzhiyun 	}
141*4882a593Smuzhiyun 	if (lineleft == 0)
142*4882a593Smuzhiyun 		return -1;
143*4882a593Smuzhiyun 	--lineleft;
144*4882a593Smuzhiyun 	return *lineptr++;
145*4882a593Smuzhiyun }
146*4882a593Smuzhiyun 
xmon_gets(char * str,int nb)147*4882a593Smuzhiyun char *xmon_gets(char *str, int nb)
148*4882a593Smuzhiyun {
149*4882a593Smuzhiyun 	char *p;
150*4882a593Smuzhiyun 	int c;
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun 	for (p = str; p < str + nb - 1; ) {
153*4882a593Smuzhiyun 		c = xmon_getchar();
154*4882a593Smuzhiyun 		if (c == -1) {
155*4882a593Smuzhiyun 			if (p == str)
156*4882a593Smuzhiyun 				return NULL;
157*4882a593Smuzhiyun 			break;
158*4882a593Smuzhiyun 		}
159*4882a593Smuzhiyun 		*p++ = c;
160*4882a593Smuzhiyun 		if (c == '\n')
161*4882a593Smuzhiyun 			break;
162*4882a593Smuzhiyun 	}
163*4882a593Smuzhiyun 	*p = 0;
164*4882a593Smuzhiyun 	return str;
165*4882a593Smuzhiyun }
166*4882a593Smuzhiyun 
xmon_printf(const char * format,...)167*4882a593Smuzhiyun void xmon_printf(const char *format, ...)
168*4882a593Smuzhiyun {
169*4882a593Smuzhiyun 	va_list args;
170*4882a593Smuzhiyun 	static char xmon_outbuf[1024];
171*4882a593Smuzhiyun 	int rc, n;
172*4882a593Smuzhiyun 
173*4882a593Smuzhiyun 	va_start(args, format);
174*4882a593Smuzhiyun 	n = vsnprintf(xmon_outbuf, sizeof(xmon_outbuf), format, args);
175*4882a593Smuzhiyun 	va_end(args);
176*4882a593Smuzhiyun 
177*4882a593Smuzhiyun 	rc = xmon_write(xmon_outbuf, n);
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun 	if (n && rc == 0) {
180*4882a593Smuzhiyun 		/* No udbg hooks, fallback to printk() - dangerous */
181*4882a593Smuzhiyun 		pr_cont("%s", xmon_outbuf);
182*4882a593Smuzhiyun 	}
183*4882a593Smuzhiyun }
184*4882a593Smuzhiyun 
xmon_puts(const char * str)185*4882a593Smuzhiyun void xmon_puts(const char *str)
186*4882a593Smuzhiyun {
187*4882a593Smuzhiyun 	xmon_write(str, strlen(str));
188*4882a593Smuzhiyun }
189