OpenCores
URL https://opencores.org/ocsvn/or1k/or1k/trunk

Subversion Repositories or1k

[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [kernel/] [printk.c] - Blame information for rev 582

Go to most recent revision | Details | Compare with Previous | View Log

Line No. Rev Author Line
1 199 simons
/*
2
 *  linux/kernel/printk.c
3
 *
4
 *  Copyright (C) 1991, 1992  Linus Torvalds
5
 *
6
 * Modified to make sys_syslog() more flexible: added commands to
7
 * return the last 4k of kernel messages, regardless of whether
8
 * they've been read or not.  Added option to suppress kernel printk's
9
 * to the console.  Added hook for sending the console messages
10
 * elsewhere, in preparation for a serial line console (someday).
11
 * Ted Ts'o, 2/11/93.
12
 */
13
 
14
#include <stdarg.h>
15
 
16
#include <asm/segment.h>
17
#include <asm/system.h>
18
 
19
#include <linux/config.h>
20
#include <linux/errno.h>
21
#include <linux/sched.h>
22
#include <linux/kernel.h>
23
#include <linux/mm.h>
24
#include <linux/tty.h>
25
#include <linux/tty_driver.h>
26
 
27
#if defined(CONFIG_REDUCED_MEMORY) && !defined(CONFIG_DUMPTOFLASH)
28
#define LOG_BUF_LEN     1024 /* Originally: 8192 */
29
#else /* !CONFIG_REDUCED_MEMORY */
30
#define LOG_BUF_LEN     8192
31
#endif /* !CONFIG_REDUCED_MEMORY */
32
 
33
static char buf[1024];
34
 
35
extern void console_print(const char *);
36
 
37
/* printk's without a loglevel use this.. */
38
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
39
 
40
/* We show everything that is MORE important than this.. */
41
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
42
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
43
 
44
unsigned long log_size = 0;
45
struct wait_queue * log_wait = NULL;
46
int console_loglevel = 8;/*DEFAULT_CONSOLE_LOGLEVEL;*/
47
 
48
static void (*console_print_proc)(const char *) = 0;
49
static char log_buf[LOG_BUF_LEN];
50
static unsigned long log_start = 0;
51
static unsigned long logged_chars = 0;
52
 
53
/*
54
 * Commands to sys_syslog:
55
 *
56
 *      0 -- Close the log.  Currently a NOP.
57
 *      1 -- Open the log. Currently a NOP.
58
 *      2 -- Read from the log.
59
 *      3 -- Read up to the last 4k of messages in the ring buffer.
60
 *      4 -- Read and clear last 4k of messages in the ring buffer
61
 *      5 -- Clear ring buffer.
62
 *      6 -- Disable printk's to console
63
 *      7 -- Enable printk's to console
64
 *      8 -- Set level of messages printed to console
65
 */
66
asmlinkage int sys_syslog(int type, char * buf, int len)
67
{
68
        unsigned long i, j, count;
69
        int do_clear = 0;
70
        char c;
71
        int error;
72
 
73
        if ((type != 3) && !suser())
74
                return -EPERM;
75
        switch (type) {
76
                case 0:          /* Close log */
77
                        return 0;
78
                case 1:         /* Open log */
79
                        return 0;
80
                case 2:         /* Read from log */
81
                        if (!buf || len < 0)
82
                                return -EINVAL;
83
                        if (!len)
84
                                return 0;
85
                        error = verify_area(VERIFY_WRITE,buf,len);
86
                        if (error)
87
                                return error;
88
                        cli();
89
                        while (!log_size) {
90
                                if (current->signal & ~current->blocked) {
91
                                        sti();
92
                                        return -ERESTARTSYS;
93
                                }
94
                                interruptible_sleep_on(&log_wait);
95
                        }
96
                        i = 0;
97
                        while (log_size && i < len) {
98
                                c = *((char *) log_buf+log_start);
99
                                log_start++;
100
                                log_size--;
101
                                log_start &= LOG_BUF_LEN-1;
102
                                sti();
103
                                put_user(c,buf);
104
                                buf++;
105
                                i++;
106
                                cli();
107
                        }
108
                        sti();
109
                        return i;
110
                case 4:         /* Read/clear last kernel messages */
111
                        do_clear = 1;
112
                        /* FALL THRU */
113
                case 3:         /* Read last kernel messages */
114
                        if (!buf || len < 0)
115
                                return -EINVAL;
116
                        if (!len)
117
                                return 0;
118
                        error = verify_area(VERIFY_WRITE,buf,len);
119
                        if (error)
120
                                return error;
121
                        count = len;
122
                        if (count > LOG_BUF_LEN)
123
                                count = LOG_BUF_LEN;
124
                        if (count > logged_chars)
125
                                count = logged_chars;
126
                        j = log_start + log_size - count;
127
                        for (i = 0; i < count; i++) {
128
                                c = *((char *) log_buf+(j++ & (LOG_BUF_LEN-1)));
129
                                put_user(c, buf++);
130
                        }
131
                        if (do_clear)
132
                                logged_chars = 0;
133
                        return i;
134
                case 5:         /* Clear ring buffer */
135
                        logged_chars = 0;
136
                        return 0;
137
                case 6:         /* Disable logging to console */
138
                        console_loglevel = MINIMUM_CONSOLE_LOGLEVEL;
139
                        return 0;
140
                case 7:         /* Enable logging to console */
141
                        console_loglevel = DEFAULT_CONSOLE_LOGLEVEL;
142
                        return 0;
143
                case 8:
144
                        if (len < 1 || len > 8)
145
                                return -EINVAL;
146
                        if (len < MINIMUM_CONSOLE_LOGLEVEL)
147
                                len = MINIMUM_CONSOLE_LOGLEVEL;
148
                        console_loglevel = len;
149
                        return 0;
150
        }
151
        return -EINVAL;
152
}
153
 
154
asmlinkage int printk(const char *fmt, ...)
155
{
156
        va_list args;
157
        int i;
158
        char *msg, *p, *buf_end;
159
        static char msg_level = -1;
160
        long flags;
161
 
162
        save_flags(flags);
163
        cli();
164
        va_start(args, fmt);
165 582 simons
 
166 199 simons
        i = vsprintf(buf + 3, fmt, args); /* hopefully i < sizeof(buf)-4 */
167
        buf_end = buf + 3 + i;
168
        va_end(args);
169 582 simons
 
170 199 simons
        for (p = buf + 3; p < buf_end; p++) {
171
                msg = p;
172
                if (msg_level < 0) {
173
                        if (
174
                                p[0] != '<' ||
175
                                p[1] < '0' ||
176
                                p[1] > '7' ||
177
                                p[2] != '>'
178
                        ) {
179
                                p -= 3;
180
                                p[0] = '<';
181
                                p[1] = DEFAULT_MESSAGE_LOGLEVEL + '0';
182
                                p[2] = '>';
183
                        } else
184
                                msg += 3;
185
                        msg_level = p[1] - '0';
186
                }
187
                for (; p < buf_end; p++) {
188
                        log_buf[(log_start+log_size) & (LOG_BUF_LEN-1)] = *p;
189
                        if (log_size < LOG_BUF_LEN)
190
                                log_size++;
191
                        else {
192
                                log_start++;
193
                                log_start &= LOG_BUF_LEN-1;
194
                        }
195
                        logged_chars++;
196
                        if (*p == '\n')
197
                                break;
198
                }
199 582 simons
 
200 199 simons
                if (msg_level < console_loglevel && console_print_proc) {
201
                        char tmp = p[1];
202
                        p[1] = '\0';
203
                        (*console_print_proc)(msg);
204
                        p[1] = tmp;
205
                }
206
                if (*p == '\n')
207
                        msg_level = -1;
208
        }
209
        restore_flags(flags);
210
        wake_up_interruptible(&log_wait);
211
        return i;
212
}
213
 
214
/*
215
 * The console driver calls this routine during kernel initialization
216
 * to register the console printing procedure with printk() and to
217
 * print any messages that were printed by the kernel before the
218
 * console driver was initialized.
219
 */
220
void register_console(void (*proc)(const char *))
221
{
222
        int     i,j;
223
        int     p = log_start;
224
        char    buf[16];
225
        char    msg_level = -1;
226
        char    *q;
227
 
228
        console_print_proc = proc;
229
 
230
        for (i=0,j=0; i < log_size; i++) {
231
                buf[j++] = log_buf[p];
232
                p++; p &= LOG_BUF_LEN-1;
233
                if (buf[j-1] != '\n' && i < log_size - 1 && j < sizeof(buf)-1)
234
                        continue;
235
                buf[j] = 0;
236
                q = buf;
237
                if (msg_level < 0) {
238
                        msg_level = buf[1] - '0';
239
                        q = buf + 3;
240
                }
241
                if (msg_level < console_loglevel)
242
                        (*proc)(q);
243
                if (buf[j-1] == '\n')
244
                        msg_level = -1;
245
                j = 0;
246
        }
247
}
248
 
249
/*
250
 *      Return log buffer address and size.
251
 */
252
unsigned long sys_getlog(char **bp)
253
{
254
        *bp = &log_buf[0];
255
        return(log_size);
256
}
257
 
258
void sys_resetlog(void)
259
{
260
        log_start = 0;
261
        log_size = 0;
262
        logged_chars = 0;
263
}
264
 
265
/*
266
 * Write a message to a certain tty, not just the console. This is used for
267
 * messages that need to be redirected to a specific tty.
268
 * We don't put it into the syslog queue right now maybe in the future if
269
 * really needed.
270
 */
271
void tty_write_message(struct tty_struct *tty, char *msg)
272
{
273
        if (tty && tty->driver.write)
274
                tty->driver.write(tty, 0, msg, strlen(msg));
275
        return;
276
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.