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 void 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 = vsprintf(printbuffer, fmt, args); 216 va_end(args); 217 218 serial_puts(printbuffer); 219 } 220 221 int fgetc(int file) 222 { 223 if (file < MAX_FILES) { 224 #if defined(CONFIG_CONSOLE_MUX) 225 /* 226 * Effectively poll for input wherever it may be available. 227 */ 228 for (;;) { 229 /* 230 * Upper layer may have already called tstc() so 231 * check for that first. 232 */ 233 if (tstcdev != NULL) 234 return console_getc(file); 235 console_tstc(file); 236 #ifdef CONFIG_WATCHDOG 237 /* 238 * If the watchdog must be rate-limited then it should 239 * already be handled in board-specific code. 240 */ 241 udelay(1); 242 #endif 243 } 244 #else 245 return console_getc(file); 246 #endif 247 } 248 249 return -1; 250 } 251 252 int ftstc(int file) 253 { 254 if (file < MAX_FILES) 255 return console_tstc(file); 256 257 return -1; 258 } 259 260 void fputc(int file, const char c) 261 { 262 if (file < MAX_FILES) 263 console_putc(file, c); 264 } 265 266 void fputs(int file, const char *s) 267 { 268 if (file < MAX_FILES) 269 console_puts(file, s); 270 } 271 272 void fprintf(int file, const char *fmt, ...) 273 { 274 va_list args; 275 uint i; 276 char printbuffer[CONFIG_SYS_PBSIZE]; 277 278 va_start(args, fmt); 279 280 /* For this to work, printbuffer must be larger than 281 * anything we ever want to print. 282 */ 283 i = vsprintf(printbuffer, fmt, args); 284 va_end(args); 285 286 /* Send to desired file */ 287 fputs(file, printbuffer); 288 } 289 290 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ 291 292 int getc(void) 293 { 294 #ifdef CONFIG_DISABLE_CONSOLE 295 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 296 return 0; 297 #endif 298 299 if (gd->flags & GD_FLG_DEVINIT) { 300 /* Get from the standard input */ 301 return fgetc(stdin); 302 } 303 304 /* Send directly to the handler */ 305 return serial_getc(); 306 } 307 308 int tstc(void) 309 { 310 #ifdef CONFIG_DISABLE_CONSOLE 311 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 312 return 0; 313 #endif 314 315 if (gd->flags & GD_FLG_DEVINIT) { 316 /* Test the standard input */ 317 return ftstc(stdin); 318 } 319 320 /* Send directly to the handler */ 321 return serial_tstc(); 322 } 323 324 void putc(const char c) 325 { 326 #ifdef CONFIG_SILENT_CONSOLE 327 if (gd->flags & GD_FLG_SILENT) 328 return; 329 #endif 330 331 #ifdef CONFIG_DISABLE_CONSOLE 332 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 333 return; 334 #endif 335 336 if (gd->flags & GD_FLG_DEVINIT) { 337 /* Send to the standard output */ 338 fputc(stdout, c); 339 } else { 340 /* Send directly to the handler */ 341 serial_putc(c); 342 } 343 } 344 345 void puts(const char *s) 346 { 347 #ifdef CONFIG_SILENT_CONSOLE 348 if (gd->flags & GD_FLG_SILENT) 349 return; 350 #endif 351 352 #ifdef CONFIG_DISABLE_CONSOLE 353 if (gd->flags & GD_FLG_DISABLE_CONSOLE) 354 return; 355 #endif 356 357 if (gd->flags & GD_FLG_DEVINIT) { 358 /* Send to the standard output */ 359 fputs(stdout, s); 360 } else { 361 /* Send directly to the handler */ 362 serial_puts(s); 363 } 364 } 365 366 void printf(const char *fmt, ...) 367 { 368 va_list args; 369 uint i; 370 char printbuffer[CONFIG_SYS_PBSIZE]; 371 372 va_start(args, fmt); 373 374 /* For this to work, printbuffer must be larger than 375 * anything we ever want to print. 376 */ 377 i = vsprintf(printbuffer, fmt, args); 378 va_end(args); 379 380 /* Print the string */ 381 puts(printbuffer); 382 } 383 384 void vprintf(const char *fmt, va_list args) 385 { 386 uint i; 387 char printbuffer[CONFIG_SYS_PBSIZE]; 388 389 /* For this to work, printbuffer must be larger than 390 * anything we ever want to print. 391 */ 392 i = vsprintf(printbuffer, fmt, args); 393 394 /* Print the string */ 395 puts(printbuffer); 396 } 397 398 /* test if ctrl-c was pressed */ 399 static int ctrlc_disabled = 0; /* see disable_ctrl() */ 400 static int ctrlc_was_pressed = 0; 401 int ctrlc(void) 402 { 403 if (!ctrlc_disabled && gd->have_console) { 404 if (tstc()) { 405 switch (getc()) { 406 case 0x03: /* ^C - Control C */ 407 ctrlc_was_pressed = 1; 408 return 1; 409 default: 410 break; 411 } 412 } 413 } 414 return 0; 415 } 416 417 /* pass 1 to disable ctrlc() checking, 0 to enable. 418 * returns previous state 419 */ 420 int disable_ctrlc(int disable) 421 { 422 int prev = ctrlc_disabled; /* save previous state */ 423 424 ctrlc_disabled = disable; 425 return prev; 426 } 427 428 int had_ctrlc (void) 429 { 430 return ctrlc_was_pressed; 431 } 432 433 void clear_ctrlc(void) 434 { 435 ctrlc_was_pressed = 0; 436 } 437 438 #ifdef CONFIG_MODEM_SUPPORT_DEBUG 439 char screen[1024]; 440 char *cursor = screen; 441 int once = 0; 442 inline void dbg(const char *fmt, ...) 443 { 444 va_list args; 445 uint i; 446 char printbuffer[CONFIG_SYS_PBSIZE]; 447 448 if (!once) { 449 memset(screen, 0, sizeof(screen)); 450 once++; 451 } 452 453 va_start(args, fmt); 454 455 /* For this to work, printbuffer must be larger than 456 * anything we ever want to print. 457 */ 458 i = vsprintf(printbuffer, fmt, args); 459 va_end(args); 460 461 if ((screen + sizeof(screen) - 1 - cursor) 462 < strlen(printbuffer) + 1) { 463 memset(screen, 0, sizeof(screen)); 464 cursor = screen; 465 } 466 sprintf(cursor, printbuffer); 467 cursor += strlen(printbuffer); 468 469 } 470 #else 471 inline void dbg(const char *fmt, ...) 472 { 473 } 474 #endif 475 476 /** U-Boot INIT FUNCTIONS *************************************************/ 477 478 struct stdio_dev *search_device(int flags, char *name) 479 { 480 struct stdio_dev *dev; 481 482 dev = stdio_get_by_name(name); 483 484 if (dev && (dev->flags & flags)) 485 return dev; 486 487 return NULL; 488 } 489 490 int console_assign(int file, char *devname) 491 { 492 int flag; 493 struct stdio_dev *dev; 494 495 /* Check for valid file */ 496 switch (file) { 497 case stdin: 498 flag = DEV_FLAGS_INPUT; 499 break; 500 case stdout: 501 case stderr: 502 flag = DEV_FLAGS_OUTPUT; 503 break; 504 default: 505 return -1; 506 } 507 508 /* Check for valid device name */ 509 510 dev = search_device(flag, devname); 511 512 if (dev) 513 return console_setfile(file, dev); 514 515 return -1; 516 } 517 518 /* Called before relocation - use serial functions */ 519 int console_init_f(void) 520 { 521 gd->have_console = 1; 522 523 #ifdef CONFIG_SILENT_CONSOLE 524 if (getenv("silent") != NULL) 525 gd->flags |= GD_FLG_SILENT; 526 #endif 527 528 return 0; 529 } 530 531 void stdio_print_current_devices(void) 532 { 533 #ifndef CONFIG_SYS_CONSOLE_INFO_QUIET 534 /* Print information */ 535 puts("In: "); 536 if (stdio_devices[stdin] == NULL) { 537 puts("No input devices available!\n"); 538 } else { 539 printf ("%s\n", stdio_devices[stdin]->name); 540 } 541 542 puts("Out: "); 543 if (stdio_devices[stdout] == NULL) { 544 puts("No output devices available!\n"); 545 } else { 546 printf ("%s\n", stdio_devices[stdout]->name); 547 } 548 549 puts("Err: "); 550 if (stdio_devices[stderr] == NULL) { 551 puts("No error devices available!\n"); 552 } else { 553 printf ("%s\n", stdio_devices[stderr]->name); 554 } 555 #endif /* CONFIG_SYS_CONSOLE_INFO_QUIET */ 556 } 557 558 #ifdef CONFIG_SYS_CONSOLE_IS_IN_ENV 559 /* Called after the relocation - use desired console functions */ 560 int console_init_r(void) 561 { 562 char *stdinname, *stdoutname, *stderrname; 563 struct stdio_dev *inputdev = NULL, *outputdev = NULL, *errdev = NULL; 564 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 565 int i; 566 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 567 #ifdef CONFIG_CONSOLE_MUX 568 int iomux_err = 0; 569 #endif 570 571 /* set default handlers at first */ 572 gd->jt[XF_getc] = serial_getc; 573 gd->jt[XF_tstc] = serial_tstc; 574 gd->jt[XF_putc] = serial_putc; 575 gd->jt[XF_puts] = serial_puts; 576 gd->jt[XF_printf] = serial_printf; 577 578 /* stdin stdout and stderr are in environment */ 579 /* scan for it */ 580 stdinname = getenv("stdin"); 581 stdoutname = getenv("stdout"); 582 stderrname = getenv("stderr"); 583 584 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */ 585 inputdev = search_device(DEV_FLAGS_INPUT, stdinname); 586 outputdev = search_device(DEV_FLAGS_OUTPUT, stdoutname); 587 errdev = search_device(DEV_FLAGS_OUTPUT, stderrname); 588 #ifdef CONFIG_CONSOLE_MUX 589 iomux_err = iomux_doenv(stdin, stdinname); 590 iomux_err += iomux_doenv(stdout, stdoutname); 591 iomux_err += iomux_doenv(stderr, stderrname); 592 if (!iomux_err) 593 /* Successful, so skip all the code below. */ 594 goto done; 595 #endif 596 } 597 /* if the devices are overwritten or not found, use default device */ 598 if (inputdev == NULL) { 599 inputdev = search_device(DEV_FLAGS_INPUT, "serial"); 600 } 601 if (outputdev == NULL) { 602 outputdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 603 } 604 if (errdev == NULL) { 605 errdev = search_device(DEV_FLAGS_OUTPUT, "serial"); 606 } 607 /* Initializes output console first */ 608 if (outputdev != NULL) { 609 /* need to set a console if not done above. */ 610 console_doenv(stdout, outputdev); 611 } 612 if (errdev != NULL) { 613 /* need to set a console if not done above. */ 614 console_doenv(stderr, errdev); 615 } 616 if (inputdev != NULL) { 617 /* need to set a console if not done above. */ 618 console_doenv(stdin, inputdev); 619 } 620 621 #ifdef CONFIG_CONSOLE_MUX 622 done: 623 #endif 624 625 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 626 627 stdio_print_current_devices(); 628 629 #ifdef CONFIG_SYS_CONSOLE_ENV_OVERWRITE 630 /* set the environment variables (will overwrite previous env settings) */ 631 for (i = 0; i < 3; i++) { 632 setenv(stdio_names[i], stdio_devices[i]->name); 633 } 634 #endif /* CONFIG_SYS_CONSOLE_ENV_OVERWRITE */ 635 636 #if 0 637 /* If nothing usable installed, use only the initial console */ 638 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 639 return 0; 640 #endif 641 return 0; 642 } 643 644 #else /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 645 646 /* Called after the relocation - use desired console functions */ 647 int console_init_r(void) 648 { 649 struct stdio_dev *inputdev = NULL, *outputdev = NULL; 650 int i; 651 struct list_head *list = stdio_get_list(); 652 struct list_head *pos; 653 struct stdio_dev *dev; 654 655 #ifdef CONFIG_SPLASH_SCREEN 656 /* 657 * suppress all output if splash screen is enabled and we have 658 * a bmp to display. We redirect the output from frame buffer 659 * console to serial console in this case or suppress it if 660 * "silent" mode was requested. 661 */ 662 if (getenv("splashimage") != NULL) { 663 if (!(gd->flags & GD_FLG_SILENT)) 664 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); 665 } 666 #endif 667 668 /* Scan devices looking for input and output devices */ 669 list_for_each(pos, list) { 670 dev = list_entry(pos, struct stdio_dev, list); 671 672 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { 673 inputdev = dev; 674 } 675 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { 676 outputdev = dev; 677 } 678 if(inputdev && outputdev) 679 break; 680 } 681 682 /* Initializes output console first */ 683 if (outputdev != NULL) { 684 console_setfile(stdout, outputdev); 685 console_setfile(stderr, outputdev); 686 #ifdef CONFIG_CONSOLE_MUX 687 console_devices[stdout][0] = outputdev; 688 console_devices[stderr][0] = outputdev; 689 #endif 690 } 691 692 /* Initializes input console */ 693 if (inputdev != NULL) { 694 console_setfile(stdin, inputdev); 695 #ifdef CONFIG_CONSOLE_MUX 696 console_devices[stdin][0] = inputdev; 697 #endif 698 } 699 700 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 701 702 stdio_print_current_devices(); 703 704 /* Setting environment variables */ 705 for (i = 0; i < 3; i++) { 706 setenv(stdio_names[i], stdio_devices[i]->name); 707 } 708 709 #if 0 710 /* If nothing usable installed, use only the initial console */ 711 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 712 return 0; 713 #endif 714 715 return 0; 716 } 717 718 #endif /* CONFIG_SYS_CONSOLE_IS_IN_ENV */ 719