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

Subversion Repositories or1k

[/] [or1k/] [trunk/] [linux/] [linux-2.4/] [kernel/] [printk.c] - Blame information for rev 1765

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 1275 phoenix
/*
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
 * Modified for sysctl support, 1/8/97, Chris Horn.
13
 * Fixed SMP synchronization, 08/08/99, Manfred Spraul
14
 *     manfreds@colorfullife.com
15
 * Rewrote bits to get rid of console_lock
16
 *      01Mar01 Andrew Morton <andrewm@uow.edu.au>
17
 */
18
 
19
#include <linux/kernel.h>
20
#include <linux/mm.h>
21
#include <linux/tty.h>
22
#include <linux/tty_driver.h>
23
#include <linux/smp_lock.h>
24
#include <linux/console.h>
25
#include <linux/init.h>
26
#include <linux/module.h>
27
#include <linux/interrupt.h>                    /* For in_interrupt() */
28
#include <linux/config.h>
29
 
30
#include <asm/uaccess.h>
31
 
32
#if !defined(CONFIG_LOG_BUF_SHIFT) || (CONFIG_LOG_BUF_SHIFT == 0)
33
#if defined(CONFIG_MULTIQUAD) || defined(CONFIG_IA64)
34
#define LOG_BUF_LEN     (65536)
35
#elif defined(CONFIG_ARCH_S390)
36
#define LOG_BUF_LEN     (131072)
37
#elif defined(CONFIG_SMP)
38
#define LOG_BUF_LEN     (32768)
39
#else   
40
#define LOG_BUF_LEN     (16384)                 /* This must be a power of two */
41
#endif
42
#else /* CONFIG_LOG_BUF_SHIFT */
43
#define LOG_BUF_LEN (1 << CONFIG_LOG_BUF_SHIFT)
44
#endif
45
 
46
#define LOG_BUF_MASK    (LOG_BUF_LEN-1)
47
 
48
#ifndef arch_consoles_callable
49
#define arch_consoles_callable() (1)
50
#endif
51
 
52
/* printk's without a loglevel use this.. */
53
#define DEFAULT_MESSAGE_LOGLEVEL 4 /* KERN_WARNING */
54
 
55
/* We show everything that is MORE important than this.. */
56
#define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */
57
#define DEFAULT_CONSOLE_LOGLEVEL 7 /* anything MORE serious than KERN_DEBUG */
58
 
59
DECLARE_WAIT_QUEUE_HEAD(log_wait);
60
 
61
int console_printk[4] = {
62
        DEFAULT_CONSOLE_LOGLEVEL,       /* console_loglevel */
63
        DEFAULT_MESSAGE_LOGLEVEL,       /* default_message_loglevel */
64
        MINIMUM_CONSOLE_LOGLEVEL,       /* minimum_console_loglevel */
65
        DEFAULT_CONSOLE_LOGLEVEL,       /* default_console_loglevel */
66
};
67
 
68
int oops_in_progress;
69
 
70
/*
71
 * console_sem protects the console_drivers list, and also
72
 * provides serialisation for access to the entire console
73
 * driver system.
74
 */
75
static DECLARE_MUTEX(console_sem);
76
struct console *console_drivers;
77
 
78
/*
79
 * logbuf_lock protects log_buf, log_start, log_end, con_start and logged_chars
80
 * It is also used in interesting ways to provide interlocking in
81
 * release_console_sem().
82
 */
83
static spinlock_t logbuf_lock = SPIN_LOCK_UNLOCKED;
84
 
85
static char log_buf[LOG_BUF_LEN];
86
#define LOG_BUF(idx) (log_buf[(idx) & LOG_BUF_MASK])
87
 
88
/*
89
 * The indices into log_buf are not constrained to LOG_BUF_LEN - they
90
 * must be masked before subscripting
91
 */
92
static unsigned long log_start;                 /* Index into log_buf: next char to be read by syslog() */
93
static unsigned long con_start;                 /* Index into log_buf: next char to be sent to consoles */
94
static unsigned long log_end;                   /* Index into log_buf: most-recently-written-char + 1 */
95
static unsigned long logged_chars;              /* Number of chars produced since last read+clear operation */
96
 
97
struct console_cmdline console_cmdline[MAX_CMDLINECONSOLES];
98
static int preferred_console = -1;
99
 
100
/* Flag: console code may call schedule() */
101
static int console_may_schedule;
102
 
103
/*
104
 *      Setup a list of consoles. Called from init/main.c
105
 */
106
static int __init console_setup(char *str)
107
{
108
        struct console_cmdline *c;
109
        char name[sizeof(c->name)];
110
        char *s, *options;
111
        int i, idx;
112
 
113
        /*
114
         *      Decode str into name, index, options.
115
         */
116
        if (str[0] >= '0' && str[0] <= '9') {
117
                strcpy(name, "ttyS");
118
                strncpy(name + 4, str, sizeof(name) - 5);
119
        } else
120
                strncpy(name, str, sizeof(name) - 1);
121
        name[sizeof(name) - 1] = 0;
122
        if ((options = strchr(str, ',')) != NULL)
123
                *(options++) = 0;
124
#ifdef __sparc__
125
        if (!strcmp(str, "ttya"))
126
                strcpy(name, "ttyS0");
127
        if (!strcmp(str, "ttyb"))
128
                strcpy(name, "ttyS1");
129
#endif
130
        for(s = name; *s; s++)
131
                if (*s >= '0' && *s <= '9')
132
                        break;
133
        idx = simple_strtoul(s, NULL, 10);
134
        *s = 0;
135
 
136
        /*
137
         *      See if this tty is not yet registered, and
138
         *      if we have a slot free.
139
         */
140
        for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++)
141
                if (strcmp(console_cmdline[i].name, name) == 0 &&
142
                          console_cmdline[i].index == idx) {
143
                                preferred_console = i;
144
                                return 1;
145
                }
146
        if (i == MAX_CMDLINECONSOLES)
147
                return 1;
148
        preferred_console = i;
149
        c = &console_cmdline[i];
150
        memcpy(c->name, name, sizeof(c->name));
151
        c->options = options;
152
        c->index = idx;
153
        return 1;
154
}
155
 
156
__setup("console=", console_setup);
157
 
158
/*
159
 * Commands to do_syslog:
160
 *
161
 *      0 -- Close the log.  Currently a NOP.
162
 *      1 -- Open the log. Currently a NOP.
163
 *      2 -- Read from the log.
164
 *      3 -- Read all messages remaining in the ring buffer.
165
 *      4 -- Read and clear all messages remaining in the ring buffer
166
 *      5 -- Clear ring buffer.
167
 *      6 -- Disable printk's to console
168
 *      7 -- Enable printk's to console
169
 *      8 -- Set level of messages printed to console
170
 *      9 -- Return number of unread characters in the log buffer
171
 */
172
int do_syslog(int type, char * buf, int len)
173
{
174
        unsigned long i, j, limit, count;
175
        int do_clear = 0;
176
        char c;
177
        int error = 0;
178
 
179
        switch (type) {
180
        case 0:          /* Close log */
181
                break;
182
        case 1:         /* Open log */
183
                break;
184
        case 2:         /* Read from log */
185
                error = -EINVAL;
186
                if (!buf || len < 0)
187
                        goto out;
188
                error = 0;
189
                if (!len)
190
                        goto out;
191
                error = verify_area(VERIFY_WRITE,buf,len);
192
                if (error)
193
                        goto out;
194
                error = wait_event_interruptible(log_wait, (log_start - log_end));
195
                if (error)
196
                        goto out;
197
                i = 0;
198
                spin_lock_irq(&logbuf_lock);
199
                while ((log_start != log_end) && i < len) {
200
                        c = LOG_BUF(log_start);
201
                        log_start++;
202
                        spin_unlock_irq(&logbuf_lock);
203
                        __put_user(c,buf);
204
                        buf++;
205
                        i++;
206
                        spin_lock_irq(&logbuf_lock);
207
                }
208
                spin_unlock_irq(&logbuf_lock);
209
                error = i;
210
                break;
211
        case 4:         /* Read/clear last kernel messages */
212
                do_clear = 1;
213
                /* FALL THRU */
214
        case 3:         /* Read last kernel messages */
215
                error = -EINVAL;
216
                if (!buf || len < 0)
217
                        goto out;
218
                error = 0;
219
                if (!len)
220
                        goto out;
221
                error = verify_area(VERIFY_WRITE,buf,len);
222
                if (error)
223
                        goto out;
224
                count = len;
225
                if (count > LOG_BUF_LEN)
226
                        count = LOG_BUF_LEN;
227
                spin_lock_irq(&logbuf_lock);
228
                if (count > logged_chars)
229
                        count = logged_chars;
230
                if (do_clear)
231
                        logged_chars = 0;
232
                limit = log_end;
233
                /*
234
                 * __put_user() could sleep, and while we sleep
235
                 * printk() could overwrite the messages
236
                 * we try to copy to user space. Therefore
237
                 * the messages are copied in reverse. <manfreds>
238
                 */
239
                for(i=0;i < count;i++) {
240
                        j = limit-1-i;
241
                        if (j+LOG_BUF_LEN < log_end)
242
                                break;
243
                        c = LOG_BUF(j);
244
                        spin_unlock_irq(&logbuf_lock);
245
                        __put_user(c,&buf[count-1-i]);
246
                        spin_lock_irq(&logbuf_lock);
247
                }
248
                spin_unlock_irq(&logbuf_lock);
249
                error = i;
250
                if(i != count) {
251
                        int offset = count-error;
252
                        /* buffer overflow during copy, correct user buffer. */
253
                        for(i=0;i<error;i++) {
254
                                __get_user(c,&buf[i+offset]);
255
                                __put_user(c,&buf[i]);
256
                        }
257
                }
258
 
259
                break;
260
        case 5:         /* Clear ring buffer */
261
                spin_lock_irq(&logbuf_lock);
262
                logged_chars = 0;
263
                spin_unlock_irq(&logbuf_lock);
264
                break;
265
        case 6:         /* Disable logging to console */
266
                spin_lock_irq(&logbuf_lock);
267
                console_loglevel = minimum_console_loglevel;
268
                spin_unlock_irq(&logbuf_lock);
269
                break;
270
        case 7:         /* Enable logging to console */
271
                spin_lock_irq(&logbuf_lock);
272
                console_loglevel = default_console_loglevel;
273
                spin_unlock_irq(&logbuf_lock);
274
                break;
275
        case 8:         /* Set level of messages printed to console */
276
                error = -EINVAL;
277
                if (len < 1 || len > 8)
278
                        goto out;
279
                if (len < minimum_console_loglevel)
280
                        len = minimum_console_loglevel;
281
                spin_lock_irq(&logbuf_lock);
282
                console_loglevel = len;
283
                spin_unlock_irq(&logbuf_lock);
284
                error = 0;
285
                break;
286
        case 9:         /* Number of chars in the log buffer */
287
                spin_lock_irq(&logbuf_lock);
288
                error = log_end - log_start;
289
                spin_unlock_irq(&logbuf_lock);
290
                break;
291
        default:
292
                error = -EINVAL;
293
                break;
294
        }
295
out:
296
        return error;
297
}
298
 
299
asmlinkage long sys_syslog(int type, char * buf, int len)
300
{
301
        if ((type != 3) && !capable(CAP_SYS_ADMIN))
302
                return -EPERM;
303
        return do_syslog(type, buf, len);
304
}
305
 
306
/*
307
 * Call the console drivers on a range of log_buf
308
 */
309
static void __call_console_drivers(unsigned long start, unsigned long end)
310
{
311
        struct console *con;
312
 
313
        for (con = console_drivers; con; con = con->next) {
314
                if ((con->flags & CON_ENABLED) && con->write)
315
                        con->write(con, &LOG_BUF(start), end - start);
316
        }
317
}
318
 
319
/*
320
 * Write out chars from start to end - 1 inclusive
321
 */
322
static void _call_console_drivers(unsigned long start, unsigned long end, int msg_log_level)
323
{
324
        if (msg_log_level < console_loglevel && console_drivers && start != end) {
325
                if ((start & LOG_BUF_MASK) > (end & LOG_BUF_MASK)) {
326
                        /* wrapped write */
327
                        __call_console_drivers(start & LOG_BUF_MASK, LOG_BUF_LEN);
328
                        __call_console_drivers(0, end & LOG_BUF_MASK);
329
                } else {
330
                        __call_console_drivers(start, end);
331
                }
332
        }
333
}
334
 
335
/*
336
 * Call the console drivers, asking them to write out
337
 * log_buf[start] to log_buf[end - 1].
338
 * The console_sem must be held.
339
 */
340
static void call_console_drivers(unsigned long start, unsigned long end)
341
{
342
        unsigned long cur_index, start_print;
343
        static int msg_level = -1;
344
 
345
        if (((long)(start - end)) > 0)
346
                BUG();
347
 
348
        cur_index = start;
349
        start_print = start;
350
        while (cur_index != end) {
351
                if (    msg_level < 0 &&
352
                        ((end - cur_index) > 2) &&
353
                        LOG_BUF(cur_index + 0) == '<' &&
354
                        LOG_BUF(cur_index + 1) >= '0' &&
355
                        LOG_BUF(cur_index + 1) <= '7' &&
356
                        LOG_BUF(cur_index + 2) == '>')
357
                {
358
                        msg_level = LOG_BUF(cur_index + 1) - '0';
359
                        cur_index += 3;
360
                        start_print = cur_index;
361
                }
362
                while (cur_index != end) {
363
                        char c = LOG_BUF(cur_index);
364
                        cur_index++;
365
 
366
                        if (c == '\n') {
367
                                if (msg_level < 0) {
368
                                        /*
369
                                         * printk() has already given us loglevel tags in
370
                                         * the buffer.  This code is here in case the
371
                                         * log buffer has wrapped right round and scribbled
372
                                         * on those tags
373
                                         */
374
                                        msg_level = default_message_loglevel;
375
                                }
376
                                _call_console_drivers(start_print, cur_index, msg_level);
377
                                msg_level = -1;
378
                                start_print = cur_index;
379
                                break;
380
                        }
381
                }
382
        }
383
        _call_console_drivers(start_print, end, msg_level);
384
}
385
 
386
static void emit_log_char(char c)
387
{
388
        LOG_BUF(log_end) = c;
389
        log_end++;
390
        if (log_end - log_start > LOG_BUF_LEN)
391
                log_start = log_end - LOG_BUF_LEN;
392
        if (log_end - con_start > LOG_BUF_LEN)
393
                con_start = log_end - LOG_BUF_LEN;
394
        if (logged_chars < LOG_BUF_LEN)
395
                logged_chars++;
396
}
397
 
398
/*
399
 * This is printk.  It can be called from any context.  We want it to work.
400
 *
401
 * We try to grab the console_sem.  If we succeed, it's easy - we log the output and
402
 * call the console drivers.  If we fail to get the semaphore we place the output
403
 * into the log buffer and return.  The current holder of the console_sem will
404
 * notice the new output in release_console_sem() and will send it to the
405
 * consoles before releasing the semaphore.
406
 *
407
 * One effect of this deferred printing is that code which calls printk() and
408
 * then changes console_loglevel may break. This is because console_loglevel
409
 * is inspected when the actual printing occurs.
410
 */
411
asmlinkage int printk(const char *fmt, ...)
412
{
413
        va_list args;
414
        unsigned long flags;
415
        int printed_len;
416
        char *p;
417
        static char printk_buf[1024];
418
        static int log_level_unknown = 1;
419
 
420
        if (oops_in_progress) {
421
                /* If a crash is occurring, make sure we can't deadlock */
422
                spin_lock_init(&logbuf_lock);
423
                /* And make sure that we print immediately */
424
                init_MUTEX(&console_sem);
425
        }
426
 
427
        /* This stops the holder of console_sem just where we want him */
428
        spin_lock_irqsave(&logbuf_lock, flags);
429
 
430
        /* Emit the output into the temporary buffer */
431
        va_start(args, fmt);
432
        printed_len = vsnprintf(printk_buf, sizeof(printk_buf), fmt, args);
433
        va_end(args);
434
 
435
        /*
436
         * Copy the output into log_buf.  If the caller didn't provide
437
         * appropriate log level tags, we insert them here
438
         */
439
        for (p = printk_buf; *p; p++) {
440
                if (log_level_unknown) {
441
                        if (p[0] != '<' || p[1] < '0' || p[1] > '7' || p[2] != '>') {
442
                                emit_log_char('<');
443
                                emit_log_char(default_message_loglevel + '0');
444
                                emit_log_char('>');
445
                        }
446
                        log_level_unknown = 0;
447
                }
448
                emit_log_char(*p);
449
                if (*p == '\n')
450
                        log_level_unknown = 1;
451
        }
452
 
453
        if (!arch_consoles_callable()) {
454
                /*
455
                 * On some architectures, the consoles are not usable
456
                 * on secondary CPUs early in the boot process.
457
                 */
458
                spin_unlock_irqrestore(&logbuf_lock, flags);
459
                goto out;
460
        }
461
        if (!down_trylock(&console_sem)) {
462
                /*
463
                 * We own the drivers.  We can drop the spinlock and let
464
                 * release_console_sem() print the text
465
                 */
466
                spin_unlock_irqrestore(&logbuf_lock, flags);
467
                console_may_schedule = 0;
468
                release_console_sem();
469
        } else {
470
                /*
471
                 * Someone else owns the drivers.  We drop the spinlock, which
472
                 * allows the semaphore holder to proceed and to call the
473
                 * console drivers with the output which we just produced.
474
                 */
475
                spin_unlock_irqrestore(&logbuf_lock, flags);
476
        }
477
out:
478
        return printed_len;
479
}
480
EXPORT_SYMBOL(printk);
481
 
482
/**
483
 * acquire_console_sem - lock the console system for exclusive use.
484
 *
485
 * Acquires a semaphore which guarantees that the caller has
486
 * exclusive access to the console system and the console_drivers list.
487
 *
488
 * Can sleep, returns nothing.
489
 */
490
void acquire_console_sem(void)
491
{
492
        if (in_interrupt())
493
                BUG();
494
        down(&console_sem);
495
        console_may_schedule = 1;
496
}
497
EXPORT_SYMBOL(acquire_console_sem);
498
 
499
/**
500
 * release_console_sem - unlock the console system
501
 *
502
 * Releases the semaphore which the caller holds on the console system
503
 * and the console driver list.
504
 *
505
 * While the semaphore was held, console output may have been buffered
506
 * by printk().  If this is the case, release_console_sem() emits
507
 * the output prior to releasing the semaphore.
508
 *
509
 * If there is output waiting for klogd, we wake it up.
510
 *
511
 * release_console_sem() may be called from any context.
512
 */
513
void release_console_sem(void)
514
{
515
        unsigned long flags;
516
        unsigned long _con_start, _log_end;
517
        unsigned long must_wake_klogd = 0;
518
 
519
        for ( ; ; ) {
520
                spin_lock_irqsave(&logbuf_lock, flags);
521
                must_wake_klogd |= log_start - log_end;
522
                if (con_start == log_end)
523
                        break;                  /* Nothing to print */
524
                _con_start = con_start;
525
                _log_end = log_end;
526
                con_start = log_end;            /* Flush */
527
                spin_unlock_irqrestore(&logbuf_lock, flags);
528
                call_console_drivers(_con_start, _log_end);
529
        }
530
        console_may_schedule = 0;
531
        up(&console_sem);
532
        spin_unlock_irqrestore(&logbuf_lock, flags);
533
        if (must_wake_klogd && !oops_in_progress)
534
                wake_up_interruptible(&log_wait);
535
}
536
 
537
/** console_conditional_schedule - yield the CPU if required
538
 *
539
 * If the console code is currently allowed to sleep, and
540
 * if this CPU should yield the CPU to another task, do
541
 * so here.
542
 *
543
 * Must be called within acquire_console_sem().
544
 */
545
void console_conditional_schedule(void)
546
{
547
        if (console_may_schedule && current->need_resched) {
548
                set_current_state(TASK_RUNNING);
549
                schedule();
550
        }
551
}
552
 
553
void console_print(const char *s)
554
{
555
        printk(KERN_EMERG "%s", s);
556
}
557
EXPORT_SYMBOL(console_print);
558
 
559
void console_unblank(void)
560
{
561
        struct console *c;
562
 
563
        /*
564
         * Try to get the console semaphore. If someone else owns it
565
         * we have to return without unblanking because console_unblank
566
         * may be called in interrupt context.
567
         */
568
        if (down_trylock(&console_sem) != 0)
569
                return;
570
        console_may_schedule = 0;
571
        for (c = console_drivers; c != NULL; c = c->next)
572
                if ((c->flags & CON_ENABLED) && c->unblank)
573
                        c->unblank();
574
        release_console_sem();
575
}
576
EXPORT_SYMBOL(console_unblank);
577
 
578
/*
579
 * The console driver calls this routine during kernel initialization
580
 * to register the console printing procedure with printk() and to
581
 * print any messages that were printed by the kernel before the
582
 * console driver was initialized.
583
 */
584
void register_console(struct console * console)
585
{
586
        int     i;
587
        unsigned long flags;
588
 
589
        /*
590
         *      See if we want to use this console driver. If we
591
         *      didn't select a console we take the first one
592
         *      that registers here.
593
         */
594
        if (preferred_console < 0) {
595
                if (console->index < 0)
596
                        console->index = 0;
597
                if (console->setup == NULL ||
598
                    console->setup(console, NULL) == 0) {
599
                        console->flags |= CON_ENABLED | CON_CONSDEV;
600
                        preferred_console = 0;
601
                }
602
        }
603
 
604
        /*
605
         *      See if this console matches one we selected on
606
         *      the command line.
607
         */
608
        for(i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0]; i++) {
609
                if (strcmp(console_cmdline[i].name, console->name) != 0)
610
                        continue;
611
                if (console->index >= 0 &&
612
                    console->index != console_cmdline[i].index)
613
                        continue;
614
                if (console->index < 0)
615
                        console->index = console_cmdline[i].index;
616
                if (console->setup &&
617
                    console->setup(console, console_cmdline[i].options) != 0)
618
                        break;
619
                console->flags |= CON_ENABLED;
620
                console->index = console_cmdline[i].index;
621
                if (i == preferred_console)
622
                        console->flags |= CON_CONSDEV;
623
                break;
624
        }
625
 
626
        if (!(console->flags & CON_ENABLED))
627
                return;
628
 
629
        /*
630
         *      Put this console in the list - keep the
631
         *      preferred driver at the head of the list.
632
         */
633
        acquire_console_sem();
634
        if ((console->flags & CON_CONSDEV) || console_drivers == NULL) {
635
                console->next = console_drivers;
636
                console_drivers = console;
637
        } else {
638
                console->next = console_drivers->next;
639
                console_drivers->next = console;
640
        }
641
        if (console->flags & CON_PRINTBUFFER) {
642
                /*
643
                 * release_console_sem() will print out the buffered messages for us.
644
                 */
645
                spin_lock_irqsave(&logbuf_lock, flags);
646
                con_start = log_start;
647
                spin_unlock_irqrestore(&logbuf_lock, flags);
648
        }
649
        release_console_sem();
650
}
651
EXPORT_SYMBOL(register_console);
652
 
653
int unregister_console(struct console * console)
654
{
655
        struct console *a,*b;
656
        int res = 1;
657
 
658
        acquire_console_sem();
659
        if (console_drivers == console) {
660
                console_drivers=console->next;
661
                res = 0;
662
        } else {
663
                for (a=console_drivers->next, b=console_drivers ;
664
                     a; b=a, a=b->next) {
665
                        if (a == console) {
666
                                b->next = a->next;
667
                                res = 0;
668
                                break;
669
                        }
670
                }
671
        }
672
 
673
        /* If last console is removed, we re-enable picking the first
674
         * one that gets registered. Without that, pmac early boot console
675
         * would prevent fbcon from taking over.
676
         */
677
        if (console_drivers == NULL)
678
                preferred_console = -1;
679
 
680
 
681
        release_console_sem();
682
        return res;
683
}
684
EXPORT_SYMBOL(unregister_console);
685
 
686
/**
687
 * tty_write_message - write a message to a certain tty, not just the console.
688
 *
689
 * This is used for messages that need to be redirected to a specific tty.
690
 * We don't put it into the syslog queue right now maybe in the future if
691
 * really needed.
692
 */
693
void tty_write_message(struct tty_struct *tty, char *msg)
694
{
695
        if (tty && tty->driver.write)
696
                tty->driver.write(tty, 0, msg, strlen(msg));
697
        return;
698
}

powered by: WebSVN 2.1.0

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