blob: 2e42f10338582dae089d8acb513d57a3f0b05ad9 [file] [log] [blame]
wdenk56f94be2002-11-05 16:35:14 +00001/*
2 * (C) Copyright 2002
3 * Detlev Zundel, DENX Software Engineering, dzu@denx.de.
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/*
25 * Logbuffer handling routines
26 */
27
28#include <common.h>
29#include <command.h>
30#include <devices.h>
31#include <logbuff.h>
32
33#if defined(CONFIG_LOGBUFFER)
34
35#define LOG_BUF_LEN (16384)
36#define LOG_BUF_MASK (LOG_BUF_LEN-1)
37
38/* Local prototypes */
39static void logbuff_putc (const char c);
40static void logbuff_puts (const char *s);
41static int logbuff_printk(const char *line);
42
43static char buf[1024];
44
45static unsigned console_loglevel = 3;
46static unsigned default_message_loglevel = 4;
47static unsigned long log_size;
48static unsigned char *log_buf=NULL;
49static unsigned long *ext_log_start, *ext_logged_chars;
50#define log_start (*ext_log_start)
51#define logged_chars (*ext_logged_chars)
52
53/* Forced by code, eh! */
54#define LOGBUFF_MAGIC 0xc0de4ced
55
56int drv_logbuff_init (void)
57{
58 device_t logdev;
59 int rc;
60
61 /* Device initialization */
62 memset (&logdev, 0, sizeof (logdev));
63
64 strcpy (logdev.name, "logbuff");
65 logdev.ext = 0; /* No extensions */
66 logdev.flags = DEV_FLAGS_OUTPUT; /* Output only */
67 logdev.putc = logbuff_putc; /* 'putc' function */
68 logdev.puts = logbuff_puts; /* 'puts' function */
69
70 rc = device_register (&logdev);
71
72 return (rc == 0) ? 1 : rc;
73}
74
75static void logbuff_putc (const char c)
76{
77 char buf[2];
78 buf[0]=c;
79 buf[1]='\0';
80 logbuff_printk(buf);
81}
82
83static void logbuff_puts (const char *s)
84{
85 char buf[512];
86
87 sprintf(buf, "%s\n", s);
88 logbuff_printk(buf);
89}
90
91void logbuff_log(char *msg)
92{
93 DECLARE_GLOBAL_DATA_PTR;
94
95 if (gd->flags & GD_FLG_RELOC) {
96 logbuff_printk(msg);
97 } else {
98 puts(msg);
99 }
100}
101
102void logbuff_reset (void)
103{
104 char *s;
105 unsigned long *ext_tag;
106
107 if ((s = getenv ("logstart")) != NULL) {
108 log_buf = (unsigned char *)simple_strtoul(s, NULL, 16);
109 ext_tag=(unsigned long *)(log_buf)-3;
110 ext_log_start=(unsigned long *)(log_buf)-2;
111 ext_logged_chars=(unsigned long *)(log_buf)-1;
112// if (*ext_tag!=LOGBUFF_MAGIC) {
113 logged_chars=log_start=0;
114 *ext_tag=LOGBUFF_MAGIC;
115// }
116 log_size=logged_chars;
117 }
118}
119
120/*
121 * Subroutine: do_log
122 *
123 * Description: Handler for 'log' command..
124 *
125 * Inputs: argv[1] contains the subcommand
126 *
127 * Return: None
128 *
129 */
130int do_log (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[])
131{
132 char *s;
133 unsigned long i;
134
135 if (log_buf==NULL) {
136 printf ("No logbuffer defined! Set 'logstart' to use this feature.\n");
137 return 1;
138 }
139
140 switch (argc) {
141
142 case 2:
143 if (strcmp(argv[1],"show") == 0) {
144 for (i=0; i<logged_chars; i++) {
145 s=log_buf+((log_start+i)&LOG_BUF_MASK);
146 putc(*s);
147 }
148 return 0;
149 } else if (strcmp(argv[1],"reset") == 0) {
150 log_start=0;
151 logged_chars=0;
152 log_size=0;
153 return 0;
154 }
155 printf ("Usage:\n%s\n", cmdtp->usage);
156 return 1;
157
158 case 3:
159 if (strcmp(argv[1],"append") == 0) {
160 logbuff_puts(argv[2]);
161 return 0;
162
163 }
164 printf ("Usage:\n%s\n", cmdtp->usage);
165 return 1;
166
167 default:
168 printf ("Usage:\n%s\n", cmdtp->usage);
169 return 1;
170 }
171}
172
173static int logbuff_printk(const char *line)
174{
175 int i;
176 char *msg, *p, *buf_end;
177 int line_feed;
178 static signed char msg_level = -1;
179
180 strcpy(buf + 3, line);
181 i = strlen(line);
182 buf_end = buf + 3 + i;
183 for (p = buf + 3; p < buf_end; p++) {
184 msg = p;
185 if (msg_level < 0) {
186 if (
187 p[0] != '<' ||
188 p[1] < '0' ||
189 p[1] > '7' ||
190 p[2] != '>'
191 ) {
192 p -= 3;
193 p[0] = '<';
194 p[1] = default_message_loglevel + '0';
195 p[2] = '>';
196 } else
197 msg += 3;
198 msg_level = p[1] - '0';
199 }
200 line_feed = 0;
201 for (; p < buf_end; p++) {
202 log_buf[(log_start+log_size) & LOG_BUF_MASK] = *p;
203 if (log_size < LOG_BUF_LEN)
204 log_size++;
205 else
206 log_start++;
207
208 logged_chars++;
209 if (*p == '\n') {
210 line_feed = 1;
211 break;
212 }
213 }
214 if (msg_level < console_loglevel) {
215 printf("%s", msg);
216 }
217 if (line_feed)
218 msg_level = -1;
219 }
220 return i;
221}
222
223#endif /* (CONFIG_LOGBUFFER) */