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