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