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> 27 #include <console.h> 28 #include <exports.h> 29 30 DECLARE_GLOBAL_DATA_PTR; 31 32 #ifdef CONFIG_AMIGAONEG3SE 33 int console_changed = 0; 34 #endif 35 36 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV 37 /* 38 * if overwrite_console returns 1, the stdin, stderr and stdout 39 * are switched to the serial port, else the settings in the 40 * environment are used 41 */ 42 #ifdef CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE 43 extern int overwrite_console(void); 44 #define OVERWRITE_CONSOLE overwrite_console() 45 #else 46 #define OVERWRITE_CONSOLE 0 47 #endif /* CONFIG_SYS_CONSOLE_OVERWRITE_ROUTINE */ 48 49 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 50 51 static int console_setfile(int file, device_t * dev) 52 { 53 int error = 0; 54 55 if (dev == NULL) 56 return -1; 57 58 switch (file) { 59 case stdin: 60 case stdout: 61 case stderr: 62 /* Start new device */ 63 if (dev->start) { 64 error = dev->start(); 65 /* If it's not started dont use it */ 66 if (error < 0) 67 break; 68 } 69 70 /* Assign the new device (leaving the existing one started) */ 71 stdio_devices[file] = dev; 72 73 /* 74 * Update monitor functions 75 * (to use the console stuff by other applications) 76 */ 77 switch (file) { 78 case stdin: 79 gd->jt[XF_getc] = dev->getc; 80 gd->jt[XF_tstc] = dev->tstc; 81 break; 82 case stdout: 83 gd->jt[XF_putc] = dev->putc; 84 gd->jt[XF_puts] = dev->puts; 85 gd->jt[XF_printf] = printf; 86 break; 87 } 88 break; 89 90 default: /* Invalid file ID */ 91 error = -1; 92 } 93 return error; 94 } 95 96 #if defined(CONFIG_CONSOLE_MUX) 97 /** Console I/O multiplexing *******************************************/ 98 99 static device_t *tstcdev; 100 device_t **console_devices[MAX_FILES]; 101 int cd_count[MAX_FILES]; 102 103 /* 104 * This depends on tstc() always being called before getc(). 105 * This is guaranteed to be true because this routine is called 106 * only from fgetc() which assures it. 107 * No attempt is made to demultiplex multiple input sources. 108 */ 109 static int console_getc(int file) 110 { 111 unsigned char ret; 112 113 /* This is never called with testcdev == NULL */ 114 ret = tstcdev->getc(); 115 tstcdev = NULL; 116 return ret; 117 } 118 119 static int console_tstc(int file) 120 { 121 int i, ret; 122 device_t *dev; 123 124 disable_ctrlc(1); 125 for (i = 0; i < cd_count[file]; i++) { 126 dev = console_devices[file][i]; 127 if (dev->tstc != NULL) { 128 ret = dev->tstc(); 129 if (ret > 0) { 130 tstcdev = dev; 131 disable_ctrlc(0); 132 return ret; 133 } 134 } 135 } 136 disable_ctrlc(0); 137 138 return 0; 139 } 140 141 static void console_putc(int file, const char c) 142 { 143 int i; 144 device_t *dev; 145 146 for (i = 0; i < cd_count[file]; i++) { 147 dev = console_devices[file][i]; 148 if (dev->putc != NULL) 149 dev->putc(c); 150 } 151 } 152 153 static void console_puts(int file, const char *s) 154 { 155 int i; 156 device_t *dev; 157 158 for (i = 0; i < cd_count[file]; i++) { 159 dev = console_devices[file][i]; 160 if (dev->puts != NULL) 161 dev->puts(s); 162 } 163 } 164 165 static inline void console_printdevs(int file) 166 { 167 iomux_printdevs(file); 168 } 169 170 static inline void console_doenv(int file, device_t *dev) 171 { 172 iomux_doenv(file, dev->name); 173 } 174 #else 175 static inline int console_getc(int file) 176 { 177 return stdio_devices[file]->getc(); 178 } 179 180 static inline int console_tstc(int file) 181 { 182 return stdio_devices[file]->tstc(); 183 } 184 185 static inline void console_putc(int file, const char c) 186 { 187 stdio_devices[file]->putc(c); 188 } 189 190 static inline void console_puts(int file, const char *s) 191 { 192 stdio_devices[file]->puts(s); 193 } 194 195 static inline void console_printdevs(int file) 196 { 197 printf("%s\n", stdio_devices[file]->name); 198 } 199 200 static inline void console_doenv(int file, device_t *dev) 201 { 202 console_setfile(file, dev); 203 } 204 #endif /* defined(CONFIG_CONSOLE_MUX) */ 205 206 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/ 207 208 void serial_printf(const char *fmt, ...) 209 { 210 va_list args; 211 uint i; 212 char printbuffer[CONFIG_SYS_PBSIZE]; 213 214 va_start(args, fmt); 215 216 /* For this to work, printbuffer must be larger than 217 * anything we ever want to print. 218 */ 219 i = vsprintf(printbuffer, fmt, args); 220 va_end(args); 221 222 serial_puts(printbuffer); 223 } 224 225 int fgetc(int file) 226 { 227 if (file < MAX_FILES) { 228 #if defined(CONFIG_CONSOLE_MUX) 229 /* 230 * Effectively poll for input wherever it may be available. 231 */ 232 for (;;) { 233 /* 234 * Upper layer may have already called tstc() so 235 * check for that first. 236 */ 237 if (tstcdev != NULL) 238 return console_getc(file); 239 console_tstc(file); 240 #ifdef CONFIG_WATCHDOG 241 /* 242 * If the watchdog must be rate-limited then it should 243 * already be handled in board-specific code. 244 */ 245 udelay(1); 246 #endif 247 } 248 #else 249 return console_getc(file); 250 #endif 251 } 252 253 return -1; 254 } 255 256 int ftstc(int file) 257 { 258 if (file < MAX_FILES) 259 return console_tstc(file); 260 261 return -1; 262 } 263 264 void fputc(int file, const char c) 265 { 266 if (file < MAX_FILES) 267 console_putc(file, c); 268 } 269 270 void fputs(int file, const char *s) 271 { 272 if (file < MAX_FILES) 273 console_puts(file, s); 274 } 275 276 void fprintf(int file, const char *fmt, ...) 277 { 278 va_list args; 279 uint i; 280 char printbuffer[CONFIG_SYS_PBSIZE]; 281 282 va_start(args, fmt); 283 284 /* For this to work, printbuffer must be larger than 285 * anything we ever want to print. 286 */ 287 i = vsprintf(printbuffer, fmt, args); 288 va_end(args); 289 290 /* Send to desired file */ 291 fputs(file, printbuffer); 292 } 293 294 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ 295 296 int getc(void) 297 { 298 #ifdef CONFIG_DISABLE_CONSOLE 299 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 300 return 0; 301 #endif 302 303 if (gd->flags & GD_FLG_DEVINIT) { 304 /* Get from the standard input */ 305 return fgetc(stdin); 306 } 307 308 /* Send directly to the handler */ 309 return serial_getc(); 310 } 311 312 int tstc(void) 313 { 314 #ifdef CONFIG_DISABLE_CONSOLE 315 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 316 return 0; 317 #endif 318 319 if (gd->flags & GD_FLG_DEVINIT) { 320 /* Test the standard input */ 321 return ftstc(stdin); 322 } 323 324 /* Send directly to the handler */ 325 return serial_tstc(); 326 } 327 328 void putc(const char c) 329 { 330 #ifdef CONFIG_SILENT_CONSOLE 331 if (gd->flags & GD_FLG_SILENT) 332 return; 333 #endif 334 335 #ifdef CONFIG_DISABLE_CONSOLE 336 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 337 return; 338 #endif 339 340 if (gd->flags & GD_FLG_DEVINIT) { 341 /* Send to the standard output */ 342 fputc(stdout, c); 343 } else { 344 /* Send directly to the handler */ 345 serial_putc(c); 346 } 347 } 348 349 void puts(const char *s) 350 { 351 #ifdef CONFIG_SILENT_CONSOLE 352 if (gd->flags & GD_FLG_SILENT) 353 return; 354 #endif 355 356 #ifdef CONFIG_DISABLE_CONSOLE 357 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 358 return; 359 #endif 360 361 if (gd->flags & GD_FLG_DEVINIT) { 362 /* Send to the standard output */ 363 fputs(stdout, s); 364 } else { 365 /* Send directly to the handler */ 366 serial_puts(s); 367 } 368 } 369 370 void printf(const char *fmt, ...) 371 { 372 va_list args; 373 uint i; 374 char printbuffer[CONFIG_SYS_PBSIZE]; 375 376 va_start(args, fmt); 377 378 /* For this to work, printbuffer must be larger than 379 * anything we ever want to print. 380 */ 381 i = vsprintf(printbuffer, fmt, args); 382 va_end(args); 383 384 /* Print the string */ 385 puts(printbuffer); 386 } 387 388 void vprintf(const char *fmt, va_list args) 389 { 390 uint i; 391 char printbuffer[CONFIG_SYS_PBSIZE]; 392 393 /* For this to work, printbuffer must be larger than 394 * anything we ever want to print. 395 */ 396 i = vsprintf(printbuffer, fmt, args); 397 398 /* Print the string */ 399 puts(printbuffer); 400 } 401 402 /* test if ctrl-c was pressed */ 403 static int ctrlc_disabled = 0; /* see disable_ctrl() */ 404 static int ctrlc_was_pressed = 0; 405 int ctrlc(void) 406 { 407 if (!ctrlc_disabled && gd->have_console) { 408 if (tstc()) { 409 switch (getc()) { 410 case 0x03: /* ^C - Control C */ 411 ctrlc_was_pressed = 1; 412 return 1; 413 default: 414 break; 415 } 416 } 417 } 418 return 0; 419 } 420 421 /* pass 1 to disable ctrlc() checking, 0 to enable. 422 * returns previous state 423 */ 424 int disable_ctrlc(int disable) 425 { 426 int prev = ctrlc_disabled; /* save previous state */ 427 428 ctrlc_disabled = disable; 429 return prev; 430 } 431 432 int had_ctrlc (void) 433 { 434 return ctrlc_was_pressed; 435 } 436 437 void clear_ctrlc(void) 438 { 439 ctrlc_was_pressed = 0; 440 } 441 442 #ifdef CONFIG_MODEM_SUPPORT_DEBUG 443 char screen[1024]; 444 char *cursor = screen; 445 int once = 0; 446 inline void dbg(const char *fmt, ...) 447 { 448 va_list args; 449 uint i; 450 char printbuffer[CONFIG_SYS_PBSIZE]; 451 452 if (!once) { 453 memset(screen, 0, sizeof(screen)); 454 once++; 455 } 456 457 va_start(args, fmt); 458 459 /* For this to work, printbuffer must be larger than 460 * anything we ever want to print. 461 */ 462 i = vsprintf(printbuffer, fmt, args); 463 va_end(args); 464 465 if ((screen + sizeof(screen) - 1 - cursor) 466 < strlen(printbuffer) + 1) { 467 memset(screen, 0, sizeof(screen)); 468 cursor = screen; 469 } 470 sprintf(cursor, printbuffer); 471 cursor += strlen(printbuffer); 472 473 } 474 #else 475 inline void dbg(const char *fmt, ...) 476 { 477 } 478 #endif 479 480 /** U-Boot INIT FUNCTIONS *************************************************/ 481 482 device_t *search_device(int flags, char *name) 483 { 484 device_t *dev; 485 486 dev = device_get_by_name(name); 487 488 if (dev && (dev->flags & flags)) 489 return dev; 490 491 return NULL; 492 } 493 494 int console_assign(int file, char *devname) 495 { 496 int flag; 497 device_t *dev; 498 499 /* Check for valid file */ 500 switch (file) { 501 case stdin: 502 flag = DEV_FLAGS_INPUT; 503 break; 504 case stdout: 505 case stderr: 506 flag = DEV_FLAGS_OUTPUT; 507 break; 508 default: 509 return -1; 510 } 511 512 /* Check for valid device name */ 513 514 dev = search_device(flag, devname); 515 516 if (dev) 517 return console_setfile(file, dev); 518 519 return -1; 520 } 521 522 /* Called before relocation - use serial functions */ 523 int console_init_f(void) 524 { 525 gd->have_console = 1; 526 527 #ifdef CONFIG_SILENT_CONSOLE 528 if (getenv("silent") != NULL) 529 gd->flags |= GD_FLG_SILENT; 530 #endif 531 532 return 0; 533 } 534 535 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV 536 /* Called after the relocation - use desired console functions */ 537 int console_init_r(void) 538 { 539 char *stdinname, *stdoutname, *stderrname; 540 device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL; 541 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 542 int i; 543 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 544 #ifdef CONFIG_CONSOLE_MUX 545 int iomux_err = 0; 546 #endif 547 548 /* set default handlers at first */ 549 gd->jt[XF_getc] = serial_getc; 550 gd->jt[XF_tstc] = serial_tstc; 551 gd->jt[XF_putc] = serial_putc; 552 gd->jt[XF_puts] = serial_puts; 553 gd->jt[XF_printf] = serial_printf; 554 555 /* stdin stdout and stderr are in environment */ 556 /* scan for it */ 557 stdinname = getenv("stdin"); 558 stdoutname = getenv("stdout"); 559 stderrname = getenv("stderr"); 560 561 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */ 562 inputdev = search_device(DEV_FLAGS_INPUT, stdinname); 563 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname); 564 errdev = search_device(DEV_FLAGS_OUTPUT, stderrname); 565 #ifdef CONFIG_CONSOLE_MUX 566 iomux_err = iomux_doenv(stdin, stdinname); 567 iomux_err += iomux_doenv(stdout, stdoutname); 568 iomux_err += iomux_doenv(stderr, stderrname); 569 if (!iomux_err) 570 /* Successful, so skip all the code below. */ 571 goto done; 572 #endif 573 } 574 /* if the devices are overwritten or not found, use default device */ 575 if (inputdev == NULL) { 576 inputdev = search_device(DEV_FLAGS_INPUT, "serial"); 577 } 578 if (outputdev == NULL) { 579 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 580 } 581 if (errdev == NULL) { 582 errdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 583 } 584 /* Initializes output console first */ 585 if (outputdev != NULL) { 586 /* need to set a console if not done above. */ 587 console_doenv(stdout, outputdev); 588 } 589 if (errdev != NULL) { 590 /* need to set a console if not done above. */ 591 console_doenv(stderr, errdev); 592 } 593 if (inputdev != NULL) { 594 /* need to set a console if not done above. */ 595 console_doenv(stdin, inputdev); 596 } 597 598 #ifdef CONFIG_CONSOLE_MUX 599 done: 600 #endif 601 602 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 603 604 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET 605 /* Print information */ 606 puts("In: "); 607 if (stdio_devices[stdin] == NULL) { 608 puts("No input devices available!\n"); 609 } else { 610 console_printdevs(stdin); 611 } 612 613 puts("Out: "); 614 if (stdio_devices[stdout] == NULL) { 615 puts("No output devices available!\n"); 616 } else { 617 console_printdevs(stdout); 618 } 619 620 puts("Err: "); 621 if (stdio_devices[stderr] == NULL) { 622 puts("No error devices available!\n"); 623 } else { 624 console_printdevs(stderr); 625 } 626 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ 627 628 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 629 /* set the environment variables (will overwrite previous env settings) */ 630 for (i = 0; i < 3; i++) { 631 setenv(stdio_names[i], stdio_devices[i]->name); 632 } 633 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 634 635 #if 0 636 /* If nothing usable installed, use only the initial console */ 637 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 638 return 0; 639 #endif 640 return 0; 641 } 642 643 #else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 644 645 /* Called after the relocation - use desired console functions */ 646 int console_init_r(void) 647 { 648 device_t *inputdev = NULL, *outputdev = NULL; 649 int i; 650 struct list_head *list = device_get_list(); 651 struct list_head *pos; 652 device_t *dev; 653 654 #ifdef CONFIG_SPLASH_SCREEN 655 /* 656 * suppress all output if splash screen is enabled and we have 657 * a bmp to display 658 */ 659 if (getenv("splashimage") != NULL) 660 gd->flags |= GD_FLG_SILENT; 661 #endif 662 663 /* Scan devices looking for input and output devices */ 664 list_for_each(pos, list) { 665 dev = list_entry(pos, device_t, list); 666 667 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { 668 inputdev = dev; 669 } 670 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { 671 outputdev = dev; 672 } 673 if(inputdev && outputdev) 674 break; 675 } 676 677 /* Initializes output console first */ 678 if (outputdev != NULL) { 679 console_setfile(stdout, outputdev); 680 console_setfile(stderr, outputdev); 681 #ifdef CONFIG_CONSOLE_MUX 682 console_devices[stdout][0] = outputdev; 683 console_devices[stderr][0] = outputdev; 684 #endif 685 } 686 687 /* Initializes input console */ 688 if (inputdev != NULL) { 689 console_setfile(stdin, inputdev); 690 #ifdef CONFIG_CONSOLE_MUX 691 console_devices[stdin][0] = inputdev; 692 #endif 693 } 694 695 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 696 697 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET 698 /* Print information */ 699 puts("In: "); 700 if (stdio_devices[stdin] == NULL) { 701 puts("No input devices available!\n"); 702 } else { 703 printf("%s\n", stdio_devices[stdin]->name); 704 } 705 706 puts("Out: "); 707 if (stdio_devices[stdout] == NULL) { 708 puts("No output devices available!\n"); 709 } else { 710 printf("%s\n", stdio_devices[stdout]->name); 711 } 712 713 puts("Err: "); 714 if (stdio_devices[stderr] == NULL) { 715 puts("No error devices available!\n"); 716 } else { 717 printf("%s\n", stdio_devices[stderr]->name); 718 } 719 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ 720 721 /* Setting environment variables */ 722 for (i = 0; i < 3; i++) { 723 setenv(stdio_names[i], stdio_devices[i]->name); 724 } 725 726 #if 0 727 /* If nothing usable installed, use only the initial console */ 728 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 729 return 0; 730 #endif 731 732 return 0; 733 } 734 735 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 736