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