i.MX introduce cpu_is_*() macros
[barebox-mini2440.git] / common / console.c
blob52d71190f8ac589807377116631f5b7911a9ae0a
1 /*
2 * (C) Copyright 2000
3 * Paolo Scaffardi, AIRVENT SAM s.p.a - RIMINI(ITALY), arsenio@tin.it
5 * See file CREDITS for list of people who contributed to this
6 * project.
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.
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.
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
24 #include <config.h>
25 #include <common.h>
26 #include <stdarg.h>
27 #include <malloc.h>
28 #include <param.h>
29 #include <console.h>
30 #include <driver.h>
31 #include <fs.h>
32 #include <reloc.h>
33 #include <init.h>
34 #include <clock.h>
35 #include <kfifo.h>
36 #include <module.h>
37 #include <list.h>
39 LIST_HEAD(console_list);
40 EXPORT_SYMBOL(console_list);
42 #define CONSOLE_UNINITIALIZED 0
43 #define CONSOLE_INIT_EARLY 1
44 #define CONSOLE_INIT_FULL 2
46 extern char version_string[];
48 static void display_banner (void)
50 printf (RELOC("\n\n%s\n\n"), RELOC_VAR(version_string));
51 printf(RELOC("Board: " CONFIG_BOARDINFO "\n"));
54 static int __initdata initialized = 0;
56 static int console_std_set(struct device_d *dev, struct param_d *param,
57 const char *val)
59 struct console_device *cdev = dev->type_data;
60 unsigned int flag = 0, i = 0;
62 if (strchr(val, 'i') && cdev->f_caps & CONSOLE_STDIN) {
63 cdev->active[i++] = 'i';
64 flag |= CONSOLE_STDIN;
67 if (strchr(val, 'o') && cdev->f_caps & CONSOLE_STDOUT) {
68 cdev->active[i++] = 'o';
69 flag |= CONSOLE_STDOUT;
72 if (strchr(val, 'e') && cdev->f_caps & CONSOLE_STDERR) {
73 cdev->active[i++] = 'e';
74 flag |= CONSOLE_STDERR;
77 cdev->active[i] = 0;
78 cdev->f_active = flag;
80 return 0;
83 static int console_baudrate_set(struct device_d *dev, struct param_d *param,
84 const char *val)
86 struct console_device *cdev = dev->type_data;
87 int baudrate;
88 unsigned char c;
90 baudrate = simple_strtoul(val, NULL, 10);
92 if (cdev->f_active) {
93 printf("## Switch baudrate to %d bps and press ENTER ...\n",
94 baudrate);
95 mdelay(50);
96 cdev->setbrg(cdev, baudrate);
97 mdelay(50);
98 do {
99 c = getc();
100 } while (c != '\r' && c != '\n');
101 } else
102 cdev->setbrg(cdev, baudrate);
104 sprintf(cdev->baudrate_string, "%d", baudrate);
106 return 0;
109 static struct kfifo *console_input_buffer;
110 static struct kfifo *console_output_buffer;
112 int getc_buffer_flush(void)
114 console_input_buffer = kfifo_alloc(1024);
115 console_output_buffer = kfifo_alloc(1024);
116 return 0;
119 postcore_initcall(getc_buffer_flush);
121 int console_register(struct console_device *newcdev)
123 struct device_d *dev = &newcdev->class_dev;
124 int first = 0;
125 char ch;
127 strcpy(dev->name, "cs");
128 dev->type_data = newcdev;
129 register_device(dev);
131 if (newcdev->setbrg) {
132 newcdev->baudrate_param.set = console_baudrate_set;
133 newcdev->baudrate_param.name = "baudrate";
134 sprintf(newcdev->baudrate_string, "%d",
135 CONFIG_BAUDRATE);
136 console_baudrate_set(dev, &newcdev->baudrate_param,
137 newcdev->baudrate_string);
138 newcdev->baudrate_param.value = newcdev->baudrate_string;
139 dev_add_param(dev, &newcdev->baudrate_param);
142 newcdev->active_param.set = console_std_set;
143 newcdev->active_param.name = "active";
144 newcdev->active_param.value = newcdev->active;
145 dev_add_param(dev, &newcdev->active_param);
147 initialized = CONSOLE_INIT_FULL;
148 #ifdef CONFIG_CONSOLE_ACTIVATE_ALL
149 console_std_set(dev, &newcdev->active_param, "ioe");
150 #endif
151 #ifdef CONFIG_CONSOLE_ACTIVATE_FIRST
152 if (list_empty(&console_list)) {
153 first = 1;
154 console_std_set(dev, &newcdev->active_param, "ioe");
156 #endif
158 list_add_tail(&newcdev->list, &console_list);
160 if (console_output_buffer) {
161 while (kfifo_getc(console_output_buffer, &ch) == 0)
162 console_putc(CONSOLE_STDOUT, ch);
163 kfifo_free(console_output_buffer);
164 console_output_buffer = NULL;
167 #ifndef CONFIG_HAS_EARLY_INIT
168 if (first)
169 display_banner();
170 #endif
172 return 0;
174 EXPORT_SYMBOL(console_register);
176 static int getc_raw(void)
178 struct console_device *cdev;
179 int active = 0;
181 while (1) {
182 for_each_console(cdev) {
183 if (!(cdev->f_active & CONSOLE_STDIN))
184 continue;
185 active = 1;
186 if (cdev->tstc(cdev))
187 return cdev->getc(cdev);
189 if (!active)
190 /* no active console found. bail out */
191 return -1;
195 int getc(void)
197 unsigned char ch;
198 uint64_t start;
201 * For 100us we read the characters from the serial driver
202 * into a kfifo. This helps us not to lose characters
203 * in small hardware fifos.
205 start = get_time_ns();
206 while (1) {
207 if (tstc()) {
208 kfifo_putc(console_input_buffer, getc_raw());
210 start = get_time_ns();
212 if (is_timeout(start, 100 * USECOND) &&
213 kfifo_len(console_input_buffer))
214 break;
217 kfifo_getc(console_input_buffer, &ch);
218 return ch;
220 EXPORT_SYMBOL(getc);
222 int fgetc(int fd)
224 char c;
226 if (!fd)
227 return getc();
228 return read(fd, &c, 1);
230 EXPORT_SYMBOL(fgetc);
232 int tstc(void)
234 struct console_device *cdev;
236 for_each_console(cdev) {
237 if (!(cdev->f_active & CONSOLE_STDIN))
238 continue;
239 if (cdev->tstc(cdev))
240 return 1;
243 return 0;
245 EXPORT_SYMBOL(tstc);
247 void __initdata *early_console_base;
249 void console_putc(unsigned int ch, char c)
251 struct console_device *cdev;
252 int init = INITDATA(initialized);
254 switch (init) {
255 case CONSOLE_UNINITIALIZED:
256 kfifo_putc(console_output_buffer, c);
257 return;
259 #ifdef CONFIG_HAS_EARLY_INIT
260 case CONSOLE_INIT_EARLY:
261 early_console_putc(INITDATA(early_console_base), c);
262 return;
263 #endif
265 case CONSOLE_INIT_FULL:
266 for_each_console(cdev) {
267 if (cdev->f_active & ch) {
268 if (c == '\n')
269 cdev->putc(cdev, '\r');
270 cdev->putc(cdev, c);
273 return;
274 default:
275 /* If we have problems inititalizing our data
276 * get them early
278 hang();
281 EXPORT_SYMBOL(console_putc);
283 int fputc(int fd, char c)
285 if(list_empty(&console_list)) {
286 if(!fd)
287 console_putc(0, c);
288 return 0;
291 if (fd == 1)
292 putchar(c);
293 else if (fd == 2)
294 eputc(c);
295 else
296 return write(fd, &c, 1);
297 return 0;
299 EXPORT_SYMBOL(fputc);
301 void console_puts(unsigned int ch, const char *str)
303 const char *s = str;
304 while (*s) {
305 if (*s == '\n')
306 console_putc(ch, '\r');
307 console_putc(ch, *s);
308 s++;
311 EXPORT_SYMBOL(console_puts);
313 int fputs(int fd, const char *s)
315 if (fd == 1)
316 puts(s);
317 else if (fd == 2)
318 eputs(s);
319 else
320 return write(fd, s, strlen(s));
321 return 0;
323 EXPORT_SYMBOL(fputs);
325 void console_flush(void)
327 struct console_device *cdev;
329 for_each_console(cdev) {
330 if (cdev->flush)
331 cdev->flush(cdev);
334 EXPORT_SYMBOL(console_flush);
336 void fprintf (int file, const char *fmt, ...)
338 va_list args;
339 uint i;
340 char printbuffer[CFG_PBSIZE];
342 va_start (args, fmt);
344 /* For this to work, printbuffer must be larger than
345 * anything we ever want to print.
347 i = vsprintf (printbuffer, fmt, args);
348 va_end (args);
350 /* Print the string */
351 fputs (file, printbuffer);
353 EXPORT_SYMBOL(fprintf);
355 int printf (const char *fmt, ...)
357 va_list args;
358 uint i;
359 char printbuffer[CFG_PBSIZE];
361 va_start (args, fmt);
363 /* For this to work, printbuffer must be larger than
364 * anything we ever want to print.
366 i = vsprintf (printbuffer, fmt, args);
367 va_end (args);
369 /* Print the string */
370 puts (printbuffer);
372 return i;
374 EXPORT_SYMBOL(printf);
376 int vprintf (const char *fmt, va_list args)
378 uint i;
379 char printbuffer[CFG_PBSIZE];
381 /* For this to work, printbuffer must be larger than
382 * anything we ever want to print.
384 i = vsprintf (printbuffer, fmt, args);
386 /* Print the string */
387 puts (printbuffer);
389 return i;
391 EXPORT_SYMBOL(vprintf);
393 #ifndef ARCH_HAS_CTRLC
394 /* test if ctrl-c was pressed */
395 int ctrlc (void)
397 if (tstc() && getc() == 3)
398 return 1;
399 return 0;
401 EXPORT_SYMBOL(ctrlc);
402 #endif /* ARCH_HAS_CTRC */
404 #ifdef CONFIG_HAS_EARLY_INIT
406 void early_console_start(const char *name, int baudrate)
408 void *base = get_early_console_base(name);
410 if (base) {
411 early_console_init(base, baudrate);
412 INITDATA(initialized) = CONSOLE_INIT_EARLY;
413 INITDATA(early_console_base) = base;
414 display_banner();
418 #endif