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