]>
Commit | Line | Data |
---|---|---|
47d1a6e1 WD |
1 | /* |
2 | * (C) Copyright 2000 | |
3 | * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it | |
4 | * | |
5 | * See file CREDITS for list of people who contributed to this | |
6 | * project. | |
7 | * | |
8 | * This program is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU General Public License as | |
10 | * published by the Free Software Foundation; either version 2 of | |
11 | * the License, or (at your option) any later version. | |
12 | * | |
13 | * This program is distributed in the hope that it will be useful, | |
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 | * GNU General Public License for more details. | |
17 | * | |
18 | * You should have received a copy of the GNU General Public License | |
19 | * along with this program; if not, write to the Free Software | |
20 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, | |
21 | * MA 02111-1307 USA | |
22 | */ | |
23 | ||
24 | #include <common.h> | |
25 | #include <stdarg.h> | |
26 | #include <malloc.h> | |
849d5d9c | 27 | #include <serial.h> |
52cb4d4f | 28 | #include <stdio_dev.h> |
27b207fd | 29 | #include <exports.h> |
849d5d9c | 30 | #include <environment.h> |
47d1a6e1 | 31 | |
d87080b7 WD |
32 | DECLARE_GLOBAL_DATA_PTR; |
33 | ||
849d5d9c JH |
34 | static int on_console(const char *name, const char *value, enum env_op op, |
35 | int flags) | |
36 | { | |
37 | int console = -1; | |
38 | ||
39 | /* Check for console redirection */ | |
40 | if (strcmp(name, "stdin") == 0) | |
41 | console = stdin; | |
42 | else if (strcmp(name, "stdout") == 0) | |
43 | console = stdout; | |
44 | else if (strcmp(name, "stderr") == 0) | |
45 | console = stderr; | |
46 | ||
47 | /* if not actually setting a console variable, we don't care */ | |
48 | if (console == -1 || (gd->flags & GD_FLG_DEVINIT) == 0) | |
49 | return 0; | |
50 | ||
51 | switch (op) { | |
52 | case env_op_create: | |
53 | case env_op_overwrite: | |
54 | ||
55 | #ifdef CONFIG_CONSOLE_MUX | |
56 | if (iomux_doenv(console, value)) | |
57 | return 1; | |
58 | #else | |
59 | /* Try assigning specified device */ | |
60 | if (console_assign(console, value) < 0) | |
61 | return 1; | |
62 | #endif /* CONFIG_CONSOLE_MUX */ | |
63 | return 0; | |
64 | ||
65 | case env_op_delete: | |
66 | if ((flags & H_FORCE) == 0) | |
67 | printf("Can't delete \"%s\"\n", name); | |
68 | return 1; | |
69 | ||
70 | default: | |
71 | return 0; | |
72 | } | |
73 | } | |
74 | U_BOOT_ENV_CALLBACK(console, on_console); | |
75 | ||
e080d545 JH |
76 | #ifdef CONFIG_SILENT_CONSOLE |
77 | static int on_silent(const char *name, const char *value, enum env_op op, | |
78 | int flags) | |
79 | { | |
80 | #ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_SET | |
81 | if (flags & H_INTERACTIVE) | |
82 | return 0; | |
83 | #endif | |
84 | #ifndef CONFIG_SILENT_CONSOLE_UPDATE_ON_RELOC | |
85 | if ((flags & H_INTERACTIVE) == 0) | |
86 | return 0; | |
87 | #endif | |
88 | ||
89 | if (value != NULL) | |
90 | gd->flags |= GD_FLG_SILENT; | |
91 | else | |
92 | gd->flags &= ~GD_FLG_SILENT; | |
93 | ||
94 | return 0; | |
95 | } | |
96 | U_BOOT_ENV_CALLBACK(silent, on_silent); | |
97 | #endif | |
98 | ||
6d0f6bcf | 99 | #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV |
47d1a6e1 WD |
100 | /* |
101 | * if overwrite_console returns 1, the stdin, stderr and stdout | |
102 | * are switched to the serial port, else the settings in the | |
103 | * environment are used | |
104 | */ | |
6d0f6bcf | 105 | #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE |
ec6f1499 JCPV |
106 | extern int overwrite_console(void); |
107 | #define OVERWRITE_CONSOLE overwrite_console() | |
47d1a6e1 | 108 | #else |
83e40ba7 | 109 | #define OVERWRITE_CONSOLE 0 |
6d0f6bcf | 110 | #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */ |
47d1a6e1 | 111 | |
6d0f6bcf | 112 | #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ |
47d1a6e1 | 113 | |
52cb4d4f | 114 | static int console_setfile(int file, struct stdio_dev * dev) |
47d1a6e1 WD |
115 | { |
116 | int error = 0; | |
117 | ||
118 | if (dev == NULL) | |
119 | return -1; | |
120 | ||
121 | switch (file) { | |
122 | case stdin: | |
123 | case stdout: | |
124 | case stderr: | |
125 | /* Start new device */ | |
126 | if (dev->start) { | |
ec6f1499 | 127 | error = dev->start(); |
47d1a6e1 WD |
128 | /* If it's not started dont use it */ |
129 | if (error < 0) | |
130 | break; | |
131 | } | |
132 | ||
133 | /* Assign the new device (leaving the existing one started) */ | |
134 | stdio_devices[file] = dev; | |
135 | ||
136 | /* | |
137 | * Update monitor functions | |
138 | * (to use the console stuff by other applications) | |
139 | */ | |
140 | switch (file) { | |
141 | case stdin: | |
27b207fd WD |
142 | gd->jt[XF_getc] = dev->getc; |
143 | gd->jt[XF_tstc] = dev->tstc; | |
47d1a6e1 WD |
144 | break; |
145 | case stdout: | |
27b207fd WD |
146 | gd->jt[XF_putc] = dev->putc; |
147 | gd->jt[XF_puts] = dev->puts; | |
148 | gd->jt[XF_printf] = printf; | |
47d1a6e1 WD |
149 | break; |
150 | } | |
151 | break; | |
152 | ||
153 | default: /* Invalid file ID */ | |
154 | error = -1; | |
155 | } | |
156 | return error; | |
157 | } | |
158 | ||
16a28ef2 GJ |
159 | #if defined(CONFIG_CONSOLE_MUX) |
160 | /** Console I/O multiplexing *******************************************/ | |
161 | ||
52cb4d4f JCPV |
162 | static struct stdio_dev *tstcdev; |
163 | struct stdio_dev **console_devices[MAX_FILES]; | |
16a28ef2 GJ |
164 | int cd_count[MAX_FILES]; |
165 | ||
166 | /* | |
167 | * This depends on tstc() always being called before getc(). | |
168 | * This is guaranteed to be true because this routine is called | |
169 | * only from fgetc() which assures it. | |
170 | * No attempt is made to demultiplex multiple input sources. | |
171 | */ | |
5f032010 | 172 | static int console_getc(int file) |
16a28ef2 GJ |
173 | { |
174 | unsigned char ret; | |
175 | ||
176 | /* This is never called with testcdev == NULL */ | |
177 | ret = tstcdev->getc(); | |
178 | tstcdev = NULL; | |
179 | return ret; | |
180 | } | |
181 | ||
5f032010 | 182 | static int console_tstc(int file) |
16a28ef2 GJ |
183 | { |
184 | int i, ret; | |
52cb4d4f | 185 | struct stdio_dev *dev; |
16a28ef2 GJ |
186 | |
187 | disable_ctrlc(1); | |
188 | for (i = 0; i < cd_count[file]; i++) { | |
189 | dev = console_devices[file][i]; | |
190 | if (dev->tstc != NULL) { | |
191 | ret = dev->tstc(); | |
192 | if (ret > 0) { | |
193 | tstcdev = dev; | |
194 | disable_ctrlc(0); | |
195 | return ret; | |
196 | } | |
197 | } | |
198 | } | |
199 | disable_ctrlc(0); | |
200 | ||
201 | return 0; | |
202 | } | |
203 | ||
5f032010 | 204 | static void console_putc(int file, const char c) |
16a28ef2 GJ |
205 | { |
206 | int i; | |
52cb4d4f | 207 | struct stdio_dev *dev; |
16a28ef2 GJ |
208 | |
209 | for (i = 0; i < cd_count[file]; i++) { | |
210 | dev = console_devices[file][i]; | |
211 | if (dev->putc != NULL) | |
212 | dev->putc(c); | |
213 | } | |
214 | } | |
215 | ||
5f032010 | 216 | static void console_puts(int file, const char *s) |
16a28ef2 GJ |
217 | { |
218 | int i; | |
52cb4d4f | 219 | struct stdio_dev *dev; |
16a28ef2 GJ |
220 | |
221 | for (i = 0; i < cd_count[file]; i++) { | |
222 | dev = console_devices[file][i]; | |
223 | if (dev->puts != NULL) | |
224 | dev->puts(s); | |
225 | } | |
226 | } | |
5f032010 JCPV |
227 | |
228 | static inline void console_printdevs(int file) | |
229 | { | |
230 | iomux_printdevs(file); | |
231 | } | |
232 | ||
52cb4d4f | 233 | static inline void console_doenv(int file, struct stdio_dev *dev) |
5f032010 JCPV |
234 | { |
235 | iomux_doenv(file, dev->name); | |
236 | } | |
237 | #else | |
238 | static inline int console_getc(int file) | |
239 | { | |
240 | return stdio_devices[file]->getc(); | |
241 | } | |
242 | ||
243 | static inline int console_tstc(int file) | |
244 | { | |
245 | return stdio_devices[file]->tstc(); | |
246 | } | |
247 | ||
248 | static inline void console_putc(int file, const char c) | |
249 | { | |
250 | stdio_devices[file]->putc(c); | |
251 | } | |
252 | ||
253 | static inline void console_puts(int file, const char *s) | |
254 | { | |
255 | stdio_devices[file]->puts(s); | |
256 | } | |
257 | ||
258 | static inline void console_printdevs(int file) | |
259 | { | |
260 | printf("%s\n", stdio_devices[file]->name); | |
261 | } | |
262 | ||
52cb4d4f | 263 | static inline void console_doenv(int file, struct stdio_dev *dev) |
5f032010 JCPV |
264 | { |
265 | console_setfile(file, dev); | |
266 | } | |
16a28ef2 GJ |
267 | #endif /* defined(CONFIG_CONSOLE_MUX) */ |
268 | ||
47d1a6e1 WD |
269 | /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/ |
270 | ||
d9c27253 | 271 | int serial_printf(const char *fmt, ...) |
47d1a6e1 WD |
272 | { |
273 | va_list args; | |
274 | uint i; | |
6d0f6bcf | 275 | char printbuffer[CONFIG_SYS_PBSIZE]; |
47d1a6e1 | 276 | |
ec6f1499 | 277 | va_start(args, fmt); |
47d1a6e1 WD |
278 | |
279 | /* For this to work, printbuffer must be larger than | |
280 | * anything we ever want to print. | |
281 | */ | |
068af6f8 | 282 | i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); |
ec6f1499 | 283 | va_end(args); |
47d1a6e1 | 284 | |
ec6f1499 | 285 | serial_puts(printbuffer); |
d9c27253 | 286 | return i; |
47d1a6e1 WD |
287 | } |
288 | ||
ec6f1499 | 289 | int fgetc(int file) |
47d1a6e1 | 290 | { |
16a28ef2 GJ |
291 | if (file < MAX_FILES) { |
292 | #if defined(CONFIG_CONSOLE_MUX) | |
293 | /* | |
294 | * Effectively poll for input wherever it may be available. | |
295 | */ | |
296 | for (;;) { | |
297 | /* | |
298 | * Upper layer may have already called tstc() so | |
299 | * check for that first. | |
300 | */ | |
301 | if (tstcdev != NULL) | |
5f032010 JCPV |
302 | return console_getc(file); |
303 | console_tstc(file); | |
16a28ef2 GJ |
304 | #ifdef CONFIG_WATCHDOG |
305 | /* | |
306 | * If the watchdog must be rate-limited then it should | |
307 | * already be handled in board-specific code. | |
308 | */ | |
309 | udelay(1); | |
310 | #endif | |
311 | } | |
312 | #else | |
5f032010 | 313 | return console_getc(file); |
16a28ef2 GJ |
314 | #endif |
315 | } | |
47d1a6e1 WD |
316 | |
317 | return -1; | |
318 | } | |
319 | ||
ec6f1499 | 320 | int ftstc(int file) |
47d1a6e1 WD |
321 | { |
322 | if (file < MAX_FILES) | |
5f032010 | 323 | return console_tstc(file); |
47d1a6e1 WD |
324 | |
325 | return -1; | |
326 | } | |
327 | ||
ec6f1499 | 328 | void fputc(int file, const char c) |
47d1a6e1 WD |
329 | { |
330 | if (file < MAX_FILES) | |
5f032010 | 331 | console_putc(file, c); |
47d1a6e1 WD |
332 | } |
333 | ||
ec6f1499 | 334 | void fputs(int file, const char *s) |
47d1a6e1 WD |
335 | { |
336 | if (file < MAX_FILES) | |
5f032010 | 337 | console_puts(file, s); |
47d1a6e1 WD |
338 | } |
339 | ||
d9c27253 | 340 | int fprintf(int file, const char *fmt, ...) |
47d1a6e1 WD |
341 | { |
342 | va_list args; | |
343 | uint i; | |
6d0f6bcf | 344 | char printbuffer[CONFIG_SYS_PBSIZE]; |
47d1a6e1 | 345 | |
ec6f1499 | 346 | va_start(args, fmt); |
47d1a6e1 WD |
347 | |
348 | /* For this to work, printbuffer must be larger than | |
349 | * anything we ever want to print. | |
350 | */ | |
068af6f8 | 351 | i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); |
ec6f1499 | 352 | va_end(args); |
47d1a6e1 WD |
353 | |
354 | /* Send to desired file */ | |
ec6f1499 | 355 | fputs(file, printbuffer); |
d9c27253 | 356 | return i; |
47d1a6e1 WD |
357 | } |
358 | ||
359 | /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ | |
360 | ||
ec6f1499 | 361 | int getc(void) |
47d1a6e1 | 362 | { |
f5c3ba79 MJ |
363 | #ifdef CONFIG_DISABLE_CONSOLE |
364 | if (gd->flags & GD_FLG_DISABLE_CONSOLE) | |
365 | return 0; | |
366 | #endif | |
367 | ||
e3e454cd GR |
368 | if (!gd->have_console) |
369 | return 0; | |
370 | ||
47d1a6e1 WD |
371 | if (gd->flags & GD_FLG_DEVINIT) { |
372 | /* Get from the standard input */ | |
ec6f1499 | 373 | return fgetc(stdin); |
47d1a6e1 WD |
374 | } |
375 | ||
376 | /* Send directly to the handler */ | |
ec6f1499 | 377 | return serial_getc(); |
47d1a6e1 WD |
378 | } |
379 | ||
ec6f1499 | 380 | int tstc(void) |
47d1a6e1 | 381 | { |
f5c3ba79 MJ |
382 | #ifdef CONFIG_DISABLE_CONSOLE |
383 | if (gd->flags & GD_FLG_DISABLE_CONSOLE) | |
384 | return 0; | |
385 | #endif | |
386 | ||
e3e454cd GR |
387 | if (!gd->have_console) |
388 | return 0; | |
389 | ||
47d1a6e1 WD |
390 | if (gd->flags & GD_FLG_DEVINIT) { |
391 | /* Test the standard input */ | |
ec6f1499 | 392 | return ftstc(stdin); |
47d1a6e1 WD |
393 | } |
394 | ||
395 | /* Send directly to the handler */ | |
ec6f1499 | 396 | return serial_tstc(); |
47d1a6e1 WD |
397 | } |
398 | ||
3fa4977a | 399 | #ifdef CONFIG_PRE_CONSOLE_BUFFER |
9558b48a GR |
400 | #define CIRC_BUF_IDX(idx) ((idx) % (unsigned long)CONFIG_PRE_CON_BUF_SZ) |
401 | ||
402 | static void pre_console_putc(const char c) | |
403 | { | |
404 | char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR; | |
405 | ||
406 | buffer[CIRC_BUF_IDX(gd->precon_buf_idx++)] = c; | |
407 | } | |
408 | ||
409 | static void pre_console_puts(const char *s) | |
410 | { | |
411 | while (*s) | |
412 | pre_console_putc(*s++); | |
413 | } | |
414 | ||
415 | static void print_pre_console_buffer(void) | |
416 | { | |
417 | unsigned long i = 0; | |
418 | char *buffer = (char *)CONFIG_PRE_CON_BUF_ADDR; | |
419 | ||
420 | if (gd->precon_buf_idx > CONFIG_PRE_CON_BUF_SZ) | |
421 | i = gd->precon_buf_idx - CONFIG_PRE_CON_BUF_SZ; | |
422 | ||
423 | while (i < gd->precon_buf_idx) | |
424 | putc(buffer[CIRC_BUF_IDX(i++)]); | |
425 | } | |
426 | #else | |
427 | static inline void pre_console_putc(const char c) {} | |
428 | static inline void pre_console_puts(const char *s) {} | |
429 | static inline void print_pre_console_buffer(void) {} | |
430 | #endif | |
431 | ||
ec6f1499 | 432 | void putc(const char c) |
47d1a6e1 | 433 | { |
a6cccaea WD |
434 | #ifdef CONFIG_SILENT_CONSOLE |
435 | if (gd->flags & GD_FLG_SILENT) | |
f6e20fc6 | 436 | return; |
a6cccaea WD |
437 | #endif |
438 | ||
f5c3ba79 MJ |
439 | #ifdef CONFIG_DISABLE_CONSOLE |
440 | if (gd->flags & GD_FLG_DISABLE_CONSOLE) | |
441 | return; | |
442 | #endif | |
443 | ||
e3e454cd | 444 | if (!gd->have_console) |
9558b48a | 445 | return pre_console_putc(c); |
e3e454cd | 446 | |
47d1a6e1 WD |
447 | if (gd->flags & GD_FLG_DEVINIT) { |
448 | /* Send to the standard output */ | |
ec6f1499 | 449 | fputc(stdout, c); |
47d1a6e1 WD |
450 | } else { |
451 | /* Send directly to the handler */ | |
ec6f1499 | 452 | serial_putc(c); |
47d1a6e1 WD |
453 | } |
454 | } | |
455 | ||
ec6f1499 | 456 | void puts(const char *s) |
47d1a6e1 | 457 | { |
a6cccaea WD |
458 | #ifdef CONFIG_SILENT_CONSOLE |
459 | if (gd->flags & GD_FLG_SILENT) | |
460 | return; | |
461 | #endif | |
462 | ||
f5c3ba79 MJ |
463 | #ifdef CONFIG_DISABLE_CONSOLE |
464 | if (gd->flags & GD_FLG_DISABLE_CONSOLE) | |
465 | return; | |
466 | #endif | |
467 | ||
e3e454cd | 468 | if (!gd->have_console) |
9558b48a | 469 | return pre_console_puts(s); |
e3e454cd | 470 | |
47d1a6e1 WD |
471 | if (gd->flags & GD_FLG_DEVINIT) { |
472 | /* Send to the standard output */ | |
ec6f1499 | 473 | fputs(stdout, s); |
47d1a6e1 WD |
474 | } else { |
475 | /* Send directly to the handler */ | |
ec6f1499 | 476 | serial_puts(s); |
47d1a6e1 WD |
477 | } |
478 | } | |
479 | ||
d9c27253 | 480 | int printf(const char *fmt, ...) |
47d1a6e1 WD |
481 | { |
482 | va_list args; | |
483 | uint i; | |
6d0f6bcf | 484 | char printbuffer[CONFIG_SYS_PBSIZE]; |
47d1a6e1 | 485 | |
9558b48a | 486 | #ifndef CONFIG_PRE_CONSOLE_BUFFER |
e3e454cd GR |
487 | if (!gd->have_console) |
488 | return 0; | |
9558b48a | 489 | #endif |
e3e454cd | 490 | |
ec6f1499 | 491 | va_start(args, fmt); |
47d1a6e1 WD |
492 | |
493 | /* For this to work, printbuffer must be larger than | |
494 | * anything we ever want to print. | |
495 | */ | |
068af6f8 | 496 | i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); |
ec6f1499 | 497 | va_end(args); |
47d1a6e1 WD |
498 | |
499 | /* Print the string */ | |
ec6f1499 | 500 | puts(printbuffer); |
d9c27253 | 501 | return i; |
47d1a6e1 WD |
502 | } |
503 | ||
d9c27253 | 504 | int vprintf(const char *fmt, va_list args) |
6dd652fa WD |
505 | { |
506 | uint i; | |
6d0f6bcf | 507 | char printbuffer[CONFIG_SYS_PBSIZE]; |
6dd652fa | 508 | |
9558b48a | 509 | #ifndef CONFIG_PRE_CONSOLE_BUFFER |
e3e454cd GR |
510 | if (!gd->have_console) |
511 | return 0; | |
9558b48a | 512 | #endif |
e3e454cd | 513 | |
6dd652fa WD |
514 | /* For this to work, printbuffer must be larger than |
515 | * anything we ever want to print. | |
516 | */ | |
068af6f8 | 517 | i = vscnprintf(printbuffer, sizeof(printbuffer), fmt, args); |
6dd652fa WD |
518 | |
519 | /* Print the string */ | |
ec6f1499 | 520 | puts(printbuffer); |
d9c27253 | 521 | return i; |
6dd652fa WD |
522 | } |
523 | ||
47d1a6e1 WD |
524 | /* test if ctrl-c was pressed */ |
525 | static int ctrlc_disabled = 0; /* see disable_ctrl() */ | |
526 | static int ctrlc_was_pressed = 0; | |
ec6f1499 | 527 | int ctrlc(void) |
47d1a6e1 | 528 | { |
47d1a6e1 | 529 | if (!ctrlc_disabled && gd->have_console) { |
ec6f1499 JCPV |
530 | if (tstc()) { |
531 | switch (getc()) { | |
47d1a6e1 WD |
532 | case 0x03: /* ^C - Control C */ |
533 | ctrlc_was_pressed = 1; | |
534 | return 1; | |
535 | default: | |
536 | break; | |
537 | } | |
538 | } | |
539 | } | |
540 | return 0; | |
541 | } | |
542 | ||
543 | /* pass 1 to disable ctrlc() checking, 0 to enable. | |
544 | * returns previous state | |
545 | */ | |
ec6f1499 | 546 | int disable_ctrlc(int disable) |
47d1a6e1 WD |
547 | { |
548 | int prev = ctrlc_disabled; /* save previous state */ | |
549 | ||
550 | ctrlc_disabled = disable; | |
551 | return prev; | |
552 | } | |
553 | ||
554 | int had_ctrlc (void) | |
555 | { | |
556 | return ctrlc_was_pressed; | |
557 | } | |
558 | ||
ec6f1499 | 559 | void clear_ctrlc(void) |
47d1a6e1 WD |
560 | { |
561 | ctrlc_was_pressed = 0; | |
562 | } | |
563 | ||
564 | #ifdef CONFIG_MODEM_SUPPORT_DEBUG | |
565 | char screen[1024]; | |
566 | char *cursor = screen; | |
567 | int once = 0; | |
568 | inline void dbg(const char *fmt, ...) | |
569 | { | |
570 | va_list args; | |
571 | uint i; | |
6d0f6bcf | 572 | char printbuffer[CONFIG_SYS_PBSIZE]; |
47d1a6e1 WD |
573 | |
574 | if (!once) { | |
575 | memset(screen, 0, sizeof(screen)); | |
576 | once++; | |
577 | } | |
578 | ||
579 | va_start(args, fmt); | |
580 | ||
581 | /* For this to work, printbuffer must be larger than | |
582 | * anything we ever want to print. | |
583 | */ | |
068af6f8 | 584 | i = vsnprintf(printbuffer, sizeof(printbuffer), fmt, args); |
47d1a6e1 WD |
585 | va_end(args); |
586 | ||
ec6f1499 JCPV |
587 | if ((screen + sizeof(screen) - 1 - cursor) |
588 | < strlen(printbuffer) + 1) { | |
47d1a6e1 WD |
589 | memset(screen, 0, sizeof(screen)); |
590 | cursor = screen; | |
591 | } | |
592 | sprintf(cursor, printbuffer); | |
593 | cursor += strlen(printbuffer); | |
594 | ||
595 | } | |
596 | #else | |
597 | inline void dbg(const char *fmt, ...) | |
598 | { | |
599 | } | |
600 | #endif | |
601 | ||
602 | /** U-Boot INIT FUNCTIONS *************************************************/ | |
603 | ||
d7be3056 | 604 | struct stdio_dev *search_device(int flags, const char *name) |
c1de7a6d | 605 | { |
52cb4d4f | 606 | struct stdio_dev *dev; |
c1de7a6d | 607 | |
52cb4d4f | 608 | dev = stdio_get_by_name(name); |
c1de7a6d | 609 | |
ec6f1499 | 610 | if (dev && (dev->flags & flags)) |
c1de7a6d JCPV |
611 | return dev; |
612 | ||
613 | return NULL; | |
614 | } | |
615 | ||
d7be3056 | 616 | int console_assign(int file, const char *devname) |
47d1a6e1 | 617 | { |
c1de7a6d | 618 | int flag; |
52cb4d4f | 619 | struct stdio_dev *dev; |
47d1a6e1 WD |
620 | |
621 | /* Check for valid file */ | |
622 | switch (file) { | |
623 | case stdin: | |
624 | flag = DEV_FLAGS_INPUT; | |
625 | break; | |
626 | case stdout: | |
627 | case stderr: | |
628 | flag = DEV_FLAGS_OUTPUT; | |
629 | break; | |
630 | default: | |
631 | return -1; | |
632 | } | |
633 | ||
634 | /* Check for valid device name */ | |
635 | ||
c1de7a6d | 636 | dev = search_device(flag, devname); |
47d1a6e1 | 637 | |
ec6f1499 JCPV |
638 | if (dev) |
639 | return console_setfile(file, dev); | |
47d1a6e1 WD |
640 | |
641 | return -1; | |
642 | } | |
643 | ||
644 | /* Called before relocation - use serial functions */ | |
ec6f1499 | 645 | int console_init_f(void) |
47d1a6e1 | 646 | { |
47d1a6e1 | 647 | gd->have_console = 1; |
f72da340 WD |
648 | |
649 | #ifdef CONFIG_SILENT_CONSOLE | |
650 | if (getenv("silent") != NULL) | |
651 | gd->flags |= GD_FLG_SILENT; | |
652 | #endif | |
653 | ||
9558b48a GR |
654 | print_pre_console_buffer(); |
655 | ||
ec6f1499 | 656 | return 0; |
47d1a6e1 WD |
657 | } |
658 | ||
7e3be7cf JCPV |
659 | void stdio_print_current_devices(void) |
660 | { | |
7e3be7cf JCPV |
661 | /* Print information */ |
662 | puts("In: "); | |
663 | if (stdio_devices[stdin] == NULL) { | |
664 | puts("No input devices available!\n"); | |
665 | } else { | |
666 | printf ("%s\n", stdio_devices[stdin]->name); | |
667 | } | |
668 | ||
669 | puts("Out: "); | |
670 | if (stdio_devices[stdout] == NULL) { | |
671 | puts("No output devices available!\n"); | |
672 | } else { | |
673 | printf ("%s\n", stdio_devices[stdout]->name); | |
674 | } | |
675 | ||
676 | puts("Err: "); | |
677 | if (stdio_devices[stderr] == NULL) { | |
678 | puts("No error devices available!\n"); | |
679 | } else { | |
680 | printf ("%s\n", stdio_devices[stderr]->name); | |
681 | } | |
7e3be7cf JCPV |
682 | } |
683 | ||
6d0f6bcf | 684 | #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV |
47d1a6e1 | 685 | /* Called after the relocation - use desired console functions */ |
ec6f1499 | 686 | int console_init_r(void) |
47d1a6e1 WD |
687 | { |
688 | char *stdinname, *stdoutname, *stderrname; | |
52cb4d4f | 689 | struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL; |
6d0f6bcf | 690 | #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE |
6e592385 | 691 | int i; |
6d0f6bcf | 692 | #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ |
16a28ef2 GJ |
693 | #ifdef CONFIG_CONSOLE_MUX |
694 | int iomux_err = 0; | |
695 | #endif | |
47d1a6e1 WD |
696 | |
697 | /* set default handlers at first */ | |
27b207fd WD |
698 | gd->jt[XF_getc] = serial_getc; |
699 | gd->jt[XF_tstc] = serial_tstc; | |
700 | gd->jt[XF_putc] = serial_putc; | |
701 | gd->jt[XF_puts] = serial_puts; | |
702 | gd->jt[XF_printf] = serial_printf; | |
47d1a6e1 WD |
703 | |
704 | /* stdin stdout and stderr are in environment */ | |
705 | /* scan for it */ | |
ec6f1499 JCPV |
706 | stdinname = getenv("stdin"); |
707 | stdoutname = getenv("stdout"); | |
708 | stderrname = getenv("stderr"); | |
47d1a6e1 | 709 | |
53677ef1 | 710 | if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */ |
ec6f1499 JCPV |
711 | inputdev = search_device(DEV_FLAGS_INPUT, stdinname); |
712 | outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname); | |
713 | errdev = search_device(DEV_FLAGS_OUTPUT, stderrname); | |
16a28ef2 GJ |
714 | #ifdef CONFIG_CONSOLE_MUX |
715 | iomux_err = iomux_doenv(stdin, stdinname); | |
716 | iomux_err += iomux_doenv(stdout, stdoutname); | |
717 | iomux_err += iomux_doenv(stderr, stderrname); | |
718 | if (!iomux_err) | |
719 | /* Successful, so skip all the code below. */ | |
720 | goto done; | |
721 | #endif | |
47d1a6e1 WD |
722 | } |
723 | /* if the devices are overwritten or not found, use default device */ | |
724 | if (inputdev == NULL) { | |
ec6f1499 | 725 | inputdev = search_device(DEV_FLAGS_INPUT, "serial"); |
47d1a6e1 WD |
726 | } |
727 | if (outputdev == NULL) { | |
ec6f1499 | 728 | outputdev = search_device(DEV_FLAGS_OUTPUT, "serial"); |
47d1a6e1 WD |
729 | } |
730 | if (errdev == NULL) { | |
ec6f1499 | 731 | errdev = search_device(DEV_FLAGS_OUTPUT, "serial"); |
47d1a6e1 WD |
732 | } |
733 | /* Initializes output console first */ | |
734 | if (outputdev != NULL) { | |
16a28ef2 | 735 | /* need to set a console if not done above. */ |
5f032010 | 736 | console_doenv(stdout, outputdev); |
47d1a6e1 WD |
737 | } |
738 | if (errdev != NULL) { | |
16a28ef2 | 739 | /* need to set a console if not done above. */ |
5f032010 | 740 | console_doenv(stderr, errdev); |
47d1a6e1 WD |
741 | } |
742 | if (inputdev != NULL) { | |
16a28ef2 | 743 | /* need to set a console if not done above. */ |
5f032010 | 744 | console_doenv(stdin, inputdev); |
47d1a6e1 WD |
745 | } |
746 | ||
16a28ef2 GJ |
747 | #ifdef CONFIG_CONSOLE_MUX |
748 | done: | |
749 | #endif | |
750 | ||
78c112c9 | 751 | #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET |
7e3be7cf | 752 | stdio_print_current_devices(); |
78c112c9 | 753 | #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ |
47d1a6e1 | 754 | |
6d0f6bcf | 755 | #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE |
47d1a6e1 WD |
756 | /* set the environment variables (will overwrite previous env settings) */ |
757 | for (i = 0; i < 3; i++) { | |
ec6f1499 | 758 | setenv(stdio_names[i], stdio_devices[i]->name); |
47d1a6e1 | 759 | } |
6d0f6bcf | 760 | #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ |
47d1a6e1 | 761 | |
c4e0057f JH |
762 | gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ |
763 | ||
47d1a6e1 WD |
764 | #if 0 |
765 | /* If nothing usable installed, use only the initial console */ | |
766 | if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) | |
ec6f1499 | 767 | return 0; |
47d1a6e1 | 768 | #endif |
ec6f1499 | 769 | return 0; |
47d1a6e1 WD |
770 | } |
771 | ||
6d0f6bcf | 772 | #else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ |
47d1a6e1 WD |
773 | |
774 | /* Called after the relocation - use desired console functions */ | |
ec6f1499 | 775 | int console_init_r(void) |
47d1a6e1 | 776 | { |
52cb4d4f | 777 | struct stdio_dev *inputdev = NULL, *outputdev = NULL; |
c1de7a6d | 778 | int i; |
52cb4d4f | 779 | struct list_head *list = stdio_get_list(); |
c1de7a6d | 780 | struct list_head *pos; |
52cb4d4f | 781 | struct stdio_dev *dev; |
47d1a6e1 | 782 | |
d791b1dc | 783 | #ifdef CONFIG_SPLASH_SCREEN |
ec6f1499 JCPV |
784 | /* |
785 | * suppress all output if splash screen is enabled and we have | |
a7490816 AG |
786 | * a bmp to display. We redirect the output from frame buffer |
787 | * console to serial console in this case or suppress it if | |
788 | * "silent" mode was requested. | |
ec6f1499 | 789 | */ |
a7490816 AG |
790 | if (getenv("splashimage") != NULL) { |
791 | if (!(gd->flags & GD_FLG_SILENT)) | |
792 | outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); | |
793 | } | |
f72da340 WD |
794 | #endif |
795 | ||
47d1a6e1 | 796 | /* Scan devices looking for input and output devices */ |
c1de7a6d | 797 | list_for_each(pos, list) { |
52cb4d4f | 798 | dev = list_entry(pos, struct stdio_dev, list); |
47d1a6e1 WD |
799 | |
800 | if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { | |
801 | inputdev = dev; | |
802 | } | |
803 | if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { | |
804 | outputdev = dev; | |
805 | } | |
c1de7a6d JCPV |
806 | if(inputdev && outputdev) |
807 | break; | |
47d1a6e1 WD |
808 | } |
809 | ||
810 | /* Initializes output console first */ | |
811 | if (outputdev != NULL) { | |
ec6f1499 JCPV |
812 | console_setfile(stdout, outputdev); |
813 | console_setfile(stderr, outputdev); | |
16a28ef2 GJ |
814 | #ifdef CONFIG_CONSOLE_MUX |
815 | console_devices[stdout][0] = outputdev; | |
816 | console_devices[stderr][0] = outputdev; | |
817 | #endif | |
47d1a6e1 WD |
818 | } |
819 | ||
820 | /* Initializes input console */ | |
821 | if (inputdev != NULL) { | |
ec6f1499 | 822 | console_setfile(stdin, inputdev); |
16a28ef2 GJ |
823 | #ifdef CONFIG_CONSOLE_MUX |
824 | console_devices[stdin][0] = inputdev; | |
825 | #endif | |
47d1a6e1 WD |
826 | } |
827 | ||
78c112c9 | 828 | #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET |
7e3be7cf | 829 | stdio_print_current_devices(); |
78c112c9 | 830 | #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ |
47d1a6e1 WD |
831 | |
832 | /* Setting environment variables */ | |
833 | for (i = 0; i < 3; i++) { | |
ec6f1499 | 834 | setenv(stdio_names[i], stdio_devices[i]->name); |
47d1a6e1 WD |
835 | } |
836 | ||
c4e0057f JH |
837 | gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ |
838 | ||
47d1a6e1 WD |
839 | #if 0 |
840 | /* If nothing usable installed, use only the initial console */ | |
841 | if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) | |
ec6f1499 | 842 | return 0; |
47d1a6e1 WD |
843 | #endif |
844 | ||
ec6f1499 | 845 | return 0; |
47d1a6e1 WD |
846 | } |
847 | ||
6d0f6bcf | 848 | #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ |