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 #ifdef CONFIG_AMIGAONEG3SE 31 int console_changed = 0; 32 #endif 33 34 #ifdef CFG_CONSOLE_IS_IN_ENV 35 /* 36 * if overwrite_console returns 1, the stdin, stderr and stdout 37 * are switched to the serial port, else the settings in the 38 * environment are used 39 */ 40 #ifdef CFG_CONSOLE_OVERWRITE_ROUTINE 41 extern int overwrite_console (void); 42 #define OVERWRITE_CONSOLE overwrite_console () 43 #else 44 #define OVERWRITE_CONSOLE 0 45 #endif /* CFG_CONSOLE_OVERWRITE_ROUTINE */ 46 47 #endif /* CFG_CONSOLE_IS_IN_ENV */ 48 49 static int console_setfile (int file, device_t * dev) 50 { 51 DECLARE_GLOBAL_DATA_PTR; 52 int error = 0; 53 54 if (dev == NULL) 55 return -1; 56 57 switch (file) { 58 case stdin: 59 case stdout: 60 case stderr: 61 /* Start new device */ 62 if (dev->start) { 63 error = dev->start (); 64 /* If it's not started dont use it */ 65 if (error < 0) 66 break; 67 } 68 69 /* Assign the new device (leaving the existing one started) */ 70 stdio_devices[file] = dev; 71 72 /* 73 * Update monitor functions 74 * (to use the console stuff by other applications) 75 */ 76 switch (file) { 77 case stdin: 78 gd->jt[XF_getc] = dev->getc; 79 gd->jt[XF_tstc] = dev->tstc; 80 break; 81 case stdout: 82 gd->jt[XF_putc] = dev->putc; 83 gd->jt[XF_puts] = dev->puts; 84 gd->jt[XF_printf] = printf; 85 break; 86 } 87 break; 88 89 default: /* Invalid file ID */ 90 error = -1; 91 } 92 return error; 93 } 94 95 /** U-Boot INITIAL CONSOLE-NOT COMPATIBLE FUNCTIONS *************************/ 96 97 void serial_printf (const char *fmt, ...) 98 { 99 va_list args; 100 uint i; 101 char printbuffer[CFG_PBSIZE]; 102 103 va_start (args, fmt); 104 105 /* For this to work, printbuffer must be larger than 106 * anything we ever want to print. 107 */ 108 i = vsprintf (printbuffer, fmt, args); 109 va_end (args); 110 111 serial_puts (printbuffer); 112 } 113 114 int fgetc (int file) 115 { 116 if (file < MAX_FILES) 117 return stdio_devices[file]->getc (); 118 119 return -1; 120 } 121 122 int ftstc (int file) 123 { 124 if (file < MAX_FILES) 125 return stdio_devices[file]->tstc (); 126 127 return -1; 128 } 129 130 void fputc (int file, const char c) 131 { 132 if (file < MAX_FILES) 133 stdio_devices[file]->putc (c); 134 } 135 136 void fputs (int file, const char *s) 137 { 138 if (file < MAX_FILES) 139 stdio_devices[file]->puts (s); 140 } 141 142 void fprintf (int file, const char *fmt, ...) 143 { 144 va_list args; 145 uint i; 146 char printbuffer[CFG_PBSIZE]; 147 148 va_start (args, fmt); 149 150 /* For this to work, printbuffer must be larger than 151 * anything we ever want to print. 152 */ 153 i = vsprintf (printbuffer, fmt, args); 154 va_end (args); 155 156 /* Send to desired file */ 157 fputs (file, printbuffer); 158 } 159 160 /** U-Boot INITIAL CONSOLE-COMPATIBLE FUNCTION *****************************/ 161 162 int getc (void) 163 { 164 DECLARE_GLOBAL_DATA_PTR; 165 166 if (gd->flags & GD_FLG_DEVINIT) { 167 /* Get from the standard input */ 168 return fgetc (stdin); 169 } 170 171 /* Send directly to the handler */ 172 return serial_getc (); 173 } 174 175 int tstc (void) 176 { 177 DECLARE_GLOBAL_DATA_PTR; 178 179 if (gd->flags & GD_FLG_DEVINIT) { 180 /* Test the standard input */ 181 return ftstc (stdin); 182 } 183 184 /* Send directly to the handler */ 185 return serial_tstc (); 186 } 187 188 void putc (const char c) 189 { 190 DECLARE_GLOBAL_DATA_PTR; 191 192 #ifdef CONFIG_SILENT_CONSOLE 193 if (gd->flags & GD_FLG_SILENT) 194 return; 195 #endif 196 197 if (gd->flags & GD_FLG_DEVINIT) { 198 /* Send to the standard output */ 199 fputc (stdout, c); 200 } else { 201 /* Send directly to the handler */ 202 serial_putc (c); 203 } 204 } 205 206 void puts (const char *s) 207 { 208 DECLARE_GLOBAL_DATA_PTR; 209 210 #ifdef CONFIG_SILENT_CONSOLE 211 if (gd->flags & GD_FLG_SILENT) 212 return; 213 #endif 214 215 if (gd->flags & GD_FLG_DEVINIT) { 216 /* Send to the standard output */ 217 fputs (stdout, s); 218 } else { 219 /* Send directly to the handler */ 220 serial_puts (s); 221 } 222 } 223 224 void printf (const char *fmt, ...) 225 { 226 va_list args; 227 uint i; 228 char printbuffer[CFG_PBSIZE]; 229 230 va_start (args, fmt); 231 232 /* For this to work, printbuffer must be larger than 233 * anything we ever want to print. 234 */ 235 i = vsprintf (printbuffer, fmt, args); 236 va_end (args); 237 238 /* Print the string */ 239 puts (printbuffer); 240 } 241 242 void vprintf (const char *fmt, va_list args) 243 { 244 uint i; 245 char printbuffer[CFG_PBSIZE]; 246 247 /* For this to work, printbuffer must be larger than 248 * anything we ever want to print. 249 */ 250 i = vsprintf (printbuffer, fmt, args); 251 252 /* Print the string */ 253 puts (printbuffer); 254 } 255 256 /* test if ctrl-c was pressed */ 257 static int ctrlc_disabled = 0; /* see disable_ctrl() */ 258 static int ctrlc_was_pressed = 0; 259 int ctrlc (void) 260 { 261 DECLARE_GLOBAL_DATA_PTR; 262 263 if (!ctrlc_disabled && gd->have_console) { 264 if (tstc ()) { 265 switch (getc ()) { 266 case 0x03: /* ^C - Control C */ 267 ctrlc_was_pressed = 1; 268 return 1; 269 default: 270 break; 271 } 272 } 273 } 274 return 0; 275 } 276 277 /* pass 1 to disable ctrlc() checking, 0 to enable. 278 * returns previous state 279 */ 280 int disable_ctrlc (int disable) 281 { 282 int prev = ctrlc_disabled; /* save previous state */ 283 284 ctrlc_disabled = disable; 285 return prev; 286 } 287 288 int had_ctrlc (void) 289 { 290 return ctrlc_was_pressed; 291 } 292 293 void clear_ctrlc (void) 294 { 295 ctrlc_was_pressed = 0; 296 } 297 298 #ifdef CONFIG_MODEM_SUPPORT_DEBUG 299 char screen[1024]; 300 char *cursor = screen; 301 int once = 0; 302 inline void dbg(const char *fmt, ...) 303 { 304 va_list args; 305 uint i; 306 char printbuffer[CFG_PBSIZE]; 307 308 if (!once) { 309 memset(screen, 0, sizeof(screen)); 310 once++; 311 } 312 313 va_start(args, fmt); 314 315 /* For this to work, printbuffer must be larger than 316 * anything we ever want to print. 317 */ 318 i = vsprintf(printbuffer, fmt, args); 319 va_end(args); 320 321 if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) { 322 memset(screen, 0, sizeof(screen)); 323 cursor = screen; 324 } 325 sprintf(cursor, printbuffer); 326 cursor += strlen(printbuffer); 327 328 } 329 #else 330 inline void dbg(const char *fmt, ...) 331 { 332 } 333 #endif 334 335 /** U-Boot INIT FUNCTIONS *************************************************/ 336 337 int console_assign (int file, char *devname) 338 { 339 int flag, i; 340 341 /* Check for valid file */ 342 switch (file) { 343 case stdin: 344 flag = DEV_FLAGS_INPUT; 345 break; 346 case stdout: 347 case stderr: 348 flag = DEV_FLAGS_OUTPUT; 349 break; 350 default: 351 return -1; 352 } 353 354 /* Check for valid device name */ 355 356 for (i = 1; i <= ListNumItems (devlist); i++) { 357 device_t *dev = ListGetPtrToItem (devlist, i); 358 359 if (strcmp (devname, dev->name) == 0) { 360 if (dev->flags & flag) 361 return console_setfile (file, dev); 362 363 return -1; 364 } 365 } 366 367 return -1; 368 } 369 370 /* Called before relocation - use serial functions */ 371 int console_init_f (void) 372 { 373 DECLARE_GLOBAL_DATA_PTR; 374 375 gd->have_console = 1; 376 377 #ifdef CONFIG_SILENT_CONSOLE 378 if (getenv("silent") != NULL) 379 gd->flags |= GD_FLG_SILENT; 380 #endif 381 382 return (0); 383 } 384 385 #if defined(CFG_CONSOLE_IS_IN_ENV) || defined(CONFIG_SPLASH_SCREEN) || defined(CONFIG_SILENT_CONSOLE) 386 /* search a device */ 387 device_t *search_device (int flags, char *name) 388 { 389 int i, items; 390 device_t *dev = NULL; 391 392 items = ListNumItems (devlist); 393 if (name == NULL) 394 return dev; 395 396 for (i = 1; i <= items; i++) { 397 dev = ListGetPtrToItem (devlist, i); 398 if ((dev->flags & flags) && (strcmp (name, dev->name) == 0)) { 399 break; 400 } 401 } 402 return dev; 403 } 404 #endif /* CFG_CONSOLE_IS_IN_ENV || CONFIG_SPLASH_SCREEN */ 405 406 #ifdef CFG_CONSOLE_IS_IN_ENV 407 /* Called after the relocation - use desired console functions */ 408 int console_init_r (void) 409 { 410 DECLARE_GLOBAL_DATA_PTR; 411 char *stdinname, *stdoutname, *stderrname; 412 device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL; 413 #ifdef CFG_CONSOLE_ENV_OVERWRITE 414 int i; 415 #endif /* CFG_CONSOLE_ENV_OVERWRITE */ 416 417 /* set default handlers at first */ 418 gd->jt[XF_getc] = serial_getc; 419 gd->jt[XF_tstc] = serial_tstc; 420 gd->jt[XF_putc] = serial_putc; 421 gd->jt[XF_puts] = serial_puts; 422 gd->jt[XF_printf] = serial_printf; 423 424 /* stdin stdout and stderr are in environment */ 425 /* scan for it */ 426 stdinname = getenv ("stdin"); 427 stdoutname = getenv ("stdout"); 428 stderrname = getenv ("stderr"); 429 430 if (OVERWRITE_CONSOLE == 0) { /* if not overwritten by config switch */ 431 inputdev = search_device (DEV_FLAGS_INPUT, stdinname); 432 outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname); 433 errdev = search_device (DEV_FLAGS_OUTPUT, stderrname); 434 } 435 /* if the devices are overwritten or not found, use default device */ 436 if (inputdev == NULL) { 437 inputdev = search_device (DEV_FLAGS_INPUT, "serial"); 438 } 439 if (outputdev == NULL) { 440 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); 441 } 442 if (errdev == NULL) { 443 errdev = search_device (DEV_FLAGS_OUTPUT, "serial"); 444 } 445 /* Initializes output console first */ 446 if (outputdev != NULL) { 447 console_setfile (stdout, outputdev); 448 } 449 if (errdev != NULL) { 450 console_setfile (stderr, errdev); 451 } 452 if (inputdev != NULL) { 453 console_setfile (stdin, inputdev); 454 } 455 456 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 457 458 #ifndef CFG_CONSOLE_INFO_QUIET 459 /* Print information */ 460 puts ("In: "); 461 if (stdio_devices[stdin] == NULL) { 462 puts ("No input devices available!\n"); 463 } else { 464 printf ("%s\n", stdio_devices[stdin]->name); 465 } 466 467 puts ("Out: "); 468 if (stdio_devices[stdout] == NULL) { 469 puts ("No output devices available!\n"); 470 } else { 471 printf ("%s\n", stdio_devices[stdout]->name); 472 } 473 474 puts ("Err: "); 475 if (stdio_devices[stderr] == NULL) { 476 puts ("No error devices available!\n"); 477 } else { 478 printf ("%s\n", stdio_devices[stderr]->name); 479 } 480 #endif /* CFG_CONSOLE_INFO_QUIET */ 481 482 #ifdef CFG_CONSOLE_ENV_OVERWRITE 483 /* set the environment variables (will overwrite previous env settings) */ 484 for (i = 0; i < 3; i++) { 485 setenv (stdio_names[i], stdio_devices[i]->name); 486 } 487 #endif /* CFG_CONSOLE_ENV_OVERWRITE */ 488 489 #if 0 490 /* If nothing usable installed, use only the initial console */ 491 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 492 return (0); 493 #endif 494 return (0); 495 } 496 497 #else /* CFG_CONSOLE_IS_IN_ENV */ 498 499 /* Called after the relocation - use desired console functions */ 500 int console_init_r (void) 501 { 502 DECLARE_GLOBAL_DATA_PTR; 503 504 device_t *inputdev = NULL, *outputdev = NULL; 505 int i, items = ListNumItems (devlist); 506 507 #ifdef CONFIG_SPLASH_SCREEN 508 /* suppress all output if splash screen is enabled and we have 509 a bmp to display */ 510 if (getenv("splashimage") != NULL) 511 outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev"); 512 #endif 513 514 #ifdef CONFIG_SILENT_CONSOLE 515 /* Suppress all output if "silent" mode requested */ 516 if (gd->flags & GD_FLG_SILENT) 517 outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev"); 518 #endif 519 520 /* Scan devices looking for input and output devices */ 521 for (i = 1; 522 (i <= items) && ((inputdev == NULL) || (outputdev == NULL)); 523 i++ 524 ) { 525 device_t *dev = ListGetPtrToItem (devlist, i); 526 527 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { 528 inputdev = dev; 529 } 530 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { 531 outputdev = dev; 532 } 533 } 534 535 /* Initializes output console first */ 536 if (outputdev != NULL) { 537 console_setfile (stdout, outputdev); 538 console_setfile (stderr, outputdev); 539 } 540 541 /* Initializes input console */ 542 if (inputdev != NULL) { 543 console_setfile (stdin, inputdev); 544 } 545 546 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 547 548 #ifndef CFG_CONSOLE_INFO_QUIET 549 /* Print information */ 550 puts ("In: "); 551 if (stdio_devices[stdin] == NULL) { 552 puts ("No input devices available!\n"); 553 } else { 554 printf ("%s\n", stdio_devices[stdin]->name); 555 } 556 557 puts ("Out: "); 558 if (stdio_devices[stdout] == NULL) { 559 puts ("No output devices available!\n"); 560 } else { 561 printf ("%s\n", stdio_devices[stdout]->name); 562 } 563 564 puts ("Err: "); 565 if (stdio_devices[stderr] == NULL) { 566 puts ("No error devices available!\n"); 567 } else { 568 printf ("%s\n", stdio_devices[stderr]->name); 569 } 570 #endif /* CFG_CONSOLE_INFO_QUIET */ 571 572 /* Setting environment variables */ 573 for (i = 0; i < 3; i++) { 574 setenv (stdio_names[i], stdio_devices[i]->name); 575 } 576 577 #if 0 578 /* If nothing usable installed, use only the initial console */ 579 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 580 return (0); 581 #endif 582 583 return (0); 584 } 585 586 #endif /* CFG_CONSOLE_IS_IN_ENV */ 587