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