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