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