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