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 if (gd->flags & GD_FLG_DEVINIT) { 195 /* Send to the standard output */ 196 fputc (stdout, c); 197 } else { 198 /* Send directly to the handler */ 199 serial_putc (c); 200 } 201 } 202 203 void puts (const char *s) 204 { 205 DECLARE_GLOBAL_DATA_PTR; 206 207 if (gd->flags & GD_FLG_DEVINIT) { 208 /* Send to the standard output */ 209 fputs (stdout, s); 210 } else { 211 /* Send directly to the handler */ 212 serial_puts (s); 213 } 214 } 215 216 void printf (const char *fmt, ...) 217 { 218 va_list args; 219 uint i; 220 char printbuffer[CFG_PBSIZE]; 221 222 va_start (args, fmt); 223 224 /* For this to work, printbuffer must be larger than 225 * anything we ever want to print. 226 */ 227 i = vsprintf (printbuffer, fmt, args); 228 va_end (args); 229 230 /* Print the string */ 231 puts (printbuffer); 232 } 233 234 void vprintf (const char *fmt, va_list args) 235 { 236 uint i; 237 char printbuffer[CFG_PBSIZE]; 238 239 /* For this to work, printbuffer must be larger than 240 * anything we ever want to print. 241 */ 242 i = vsprintf (printbuffer, fmt, args); 243 244 /* Print the string */ 245 puts (printbuffer); 246 } 247 248 /* test if ctrl-c was pressed */ 249 static int ctrlc_disabled = 0; /* see disable_ctrl() */ 250 static int ctrlc_was_pressed = 0; 251 int ctrlc (void) 252 { 253 DECLARE_GLOBAL_DATA_PTR; 254 255 if (!ctrlc_disabled && gd->have_console) { 256 if (tstc ()) { 257 switch (getc ()) { 258 case 0x03: /* ^C - Control C */ 259 ctrlc_was_pressed = 1; 260 return 1; 261 default: 262 break; 263 } 264 } 265 } 266 return 0; 267 } 268 269 /* pass 1 to disable ctrlc() checking, 0 to enable. 270 * returns previous state 271 */ 272 int disable_ctrlc (int disable) 273 { 274 int prev = ctrlc_disabled; /* save previous state */ 275 276 ctrlc_disabled = disable; 277 return prev; 278 } 279 280 int had_ctrlc (void) 281 { 282 return ctrlc_was_pressed; 283 } 284 285 void clear_ctrlc (void) 286 { 287 ctrlc_was_pressed = 0; 288 } 289 290 #ifdef CONFIG_MODEM_SUPPORT_DEBUG 291 char screen[1024]; 292 char *cursor = screen; 293 int once = 0; 294 inline void dbg(const char *fmt, ...) 295 { 296 va_list args; 297 uint i; 298 char printbuffer[CFG_PBSIZE]; 299 300 if (!once) { 301 memset(screen, 0, sizeof(screen)); 302 once++; 303 } 304 305 va_start(args, fmt); 306 307 /* For this to work, printbuffer must be larger than 308 * anything we ever want to print. 309 */ 310 i = vsprintf(printbuffer, fmt, args); 311 va_end(args); 312 313 if ((screen + sizeof(screen) - 1 - cursor) < strlen(printbuffer)+1) { 314 memset(screen, 0, sizeof(screen)); 315 cursor = screen; 316 } 317 sprintf(cursor, printbuffer); 318 cursor += strlen(printbuffer); 319 320 } 321 #else 322 inline void dbg(const char *fmt, ...) 323 { 324 } 325 #endif 326 327 /** U-Boot INIT FUNCTIONS *************************************************/ 328 329 int console_assign (int file, char *devname) 330 { 331 int flag, i; 332 333 /* Check for valid file */ 334 switch (file) { 335 case stdin: 336 flag = DEV_FLAGS_INPUT; 337 break; 338 case stdout: 339 case stderr: 340 flag = DEV_FLAGS_OUTPUT; 341 break; 342 default: 343 return -1; 344 } 345 346 /* Check for valid device name */ 347 348 for (i = 1; i <= ListNumItems (devlist); i++) { 349 device_t *dev = ListGetPtrToItem (devlist, i); 350 351 if (strcmp (devname, dev->name) == 0) { 352 if (dev->flags & flag) 353 return console_setfile (file, dev); 354 355 return -1; 356 } 357 } 358 359 return -1; 360 } 361 362 /* Called before relocation - use serial functions */ 363 int console_init_f (void) 364 { 365 DECLARE_GLOBAL_DATA_PTR; 366 367 gd->have_console = 1; 368 369 #ifdef CONFIG_SILENT_CONSOLE 370 if (getenv("silent") != NULL) 371 gd->flags |= GD_FLG_SILENT; 372 #endif 373 374 return (0); 375 } 376 377 #if defined(CFG_CONSOLE_IS_IN_ENV) || defined(CONFIG_SPLASH_SCREEN) || defined(CONFIG_SILENT_CONSOLE) 378 /* search a device */ 379 device_t *search_device (int flags, char *name) 380 { 381 int i, items; 382 device_t *dev = NULL; 383 384 items = ListNumItems (devlist); 385 if (name == NULL) 386 return dev; 387 388 for (i = 1; i <= items; i++) { 389 dev = ListGetPtrToItem (devlist, i); 390 if ((dev->flags & flags) && (strcmp (name, dev->name) == 0)) { 391 break; 392 } 393 } 394 return dev; 395 } 396 #endif /* CFG_CONSOLE_IS_IN_ENV || CONFIG_SPLASH_SCREEN */ 397 398 #ifdef CFG_CONSOLE_IS_IN_ENV 399 /* Called after the relocation - use desired console functions */ 400 int console_init_r (void) 401 { 402 DECLARE_GLOBAL_DATA_PTR; 403 char *stdinname, *stdoutname, *stderrname; 404 device_t *inputdev = NULL, *outputdev = NULL, *errdev = NULL; 405 406 /* set default handlers at first */ 407 gd->jt[XF_getc] = serial_getc; 408 gd->jt[XF_tstc] = serial_tstc; 409 gd->jt[XF_putc] = serial_putc; 410 gd->jt[XF_puts] = serial_puts; 411 gd->jt[XF_printf] = serial_printf; 412 413 /* stdin stdout and stderr are in environment */ 414 /* scan for it */ 415 stdinname = getenv ("stdin"); 416 stdoutname = getenv ("stdout"); 417 stderrname = getenv ("stderr"); 418 419 if (overwrite_console () == 0) { /* if not overwritten by config switch */ 420 inputdev = search_device (DEV_FLAGS_INPUT, stdinname); 421 outputdev = search_device (DEV_FLAGS_OUTPUT, stdoutname); 422 errdev = search_device (DEV_FLAGS_OUTPUT, stderrname); 423 } 424 /* if the devices are overwritten or not found, use default device */ 425 if (inputdev == NULL) { 426 inputdev = search_device (DEV_FLAGS_INPUT, "serial"); 427 } 428 if (outputdev == NULL) { 429 outputdev = search_device (DEV_FLAGS_OUTPUT, "serial"); 430 } 431 if (errdev == NULL) { 432 errdev = search_device (DEV_FLAGS_OUTPUT, "serial"); 433 } 434 /* Initializes output console first */ 435 if (outputdev != NULL) { 436 console_setfile (stdout, outputdev); 437 } 438 if (errdev != NULL) { 439 console_setfile (stderr, errdev); 440 } 441 if (inputdev != NULL) { 442 console_setfile (stdin, inputdev); 443 } 444 445 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 446 447 #ifndef CFG_CONSOLE_INFO_QUIET 448 /* Print information */ 449 printf ("In: "); 450 if (stdio_devices[stdin] == NULL) { 451 printf ("No input devices available!\n"); 452 } else { 453 printf ("%s\n", stdio_devices[stdin]->name); 454 } 455 456 printf ("Out: "); 457 if (stdio_devices[stdout] == NULL) { 458 printf ("No output devices available!\n"); 459 } else { 460 printf ("%s\n", stdio_devices[stdout]->name); 461 } 462 463 printf ("Err: "); 464 if (stdio_devices[stderr] == NULL) { 465 printf ("No error devices available!\n"); 466 } else { 467 printf ("%s\n", stdio_devices[stderr]->name); 468 } 469 #endif /* CFG_CONSOLE_INFO_QUIET */ 470 471 #ifdef CFG_CONSOLE_ENV_OVERWRITE 472 /* set the environment variables (will overwrite previous env settings) */ 473 for (i = 0; i < 3; i++) { 474 setenv (stdio_names[i], stdio_devices[i]->name); 475 } 476 #endif /* CFG_CONSOLE_ENV_OVERWRITE */ 477 478 #if 0 479 /* If nothing usable installed, use only the initial console */ 480 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 481 return (0); 482 #endif 483 return (0); 484 } 485 486 #else /* CFG_CONSOLE_IS_IN_ENV */ 487 488 /* Called after the relocation - use desired console functions */ 489 int console_init_r (void) 490 { 491 DECLARE_GLOBAL_DATA_PTR; 492 493 device_t *inputdev = NULL, *outputdev = NULL; 494 int i, items = ListNumItems (devlist); 495 496 #ifdef CONFIG_SPLASH_SCREEN 497 /* suppress all output if splash screen is enabled and we have 498 a bmp to display */ 499 if (getenv("splashimage") != NULL) 500 outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev"); 501 #endif 502 503 #ifdef CONFIG_SILENT_CONSOLE 504 /* Suppress all output if "silent" mode requested */ 505 if (gd->flags & GD_FLG_SILENT) 506 outputdev = search_device (DEV_FLAGS_OUTPUT, "nulldev"); 507 #endif 508 509 /* Scan devices looking for input and output devices */ 510 for (i = 1; 511 (i <= items) && ((inputdev == NULL) || (outputdev == NULL)); 512 i++ 513 ) { 514 device_t *dev = ListGetPtrToItem (devlist, i); 515 516 if ((dev->flags & DEV_FLAGS_INPUT) && (inputdev == NULL)) { 517 inputdev = dev; 518 } 519 if ((dev->flags & DEV_FLAGS_OUTPUT) && (outputdev == NULL)) { 520 outputdev = dev; 521 } 522 } 523 524 /* Initializes output console first */ 525 if (outputdev != NULL) { 526 console_setfile (stdout, outputdev); 527 console_setfile (stderr, outputdev); 528 } 529 530 /* Initializes input console */ 531 if (inputdev != NULL) { 532 console_setfile (stdin, inputdev); 533 } 534 535 gd->flags |= GD_FLG_DEVINIT; /* device initialization completed */ 536 537 #ifndef CFG_CONSOLE_INFO_QUIET 538 /* Print information */ 539 printf ("In: "); 540 if (stdio_devices[stdin] == NULL) { 541 printf ("No input devices available!\n"); 542 } else { 543 printf ("%s\n", stdio_devices[stdin]->name); 544 } 545 546 printf ("Out: "); 547 if (stdio_devices[stdout] == NULL) { 548 printf ("No output devices available!\n"); 549 } else { 550 printf ("%s\n", stdio_devices[stdout]->name); 551 } 552 553 printf ("Err: "); 554 if (stdio_devices[stderr] == NULL) { 555 printf ("No error devices available!\n"); 556 } else { 557 printf ("%s\n", stdio_devices[stderr]->name); 558 } 559 #endif /* CFG_CONSOLE_INFO_QUIET */ 560 561 /* Setting environment variables */ 562 for (i = 0; i < 3; i++) { 563 setenv (stdio_names[i], stdio_devices[i]->name); 564 } 565 566 #if 0 567 /* If nothing usable installed, use only the initial console */ 568 if ((stdio_devices[stdin] == NULL) && (stdio_devices[stdout] == NULL)) 569 return (0); 570 #endif 571 572 return (0); 573 } 574 575 #endif /* CFG_CONSOLE_IS_IN_ENV */ 576