Subversion Repositories HelenOS

Rev

Rev 3022 | Rev 4201 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 3022 Rev 4055
Line 33... Line 33...
33
/** @file
33
/** @file
34
 */
34
 */
35
 
35
 
36
#include <console/console.h>
36
#include <console/console.h>
37
#include <console/chardev.h>
37
#include <console/chardev.h>
-
 
38
#include <sysinfo/sysinfo.h>
38
#include <synch/waitq.h>
39
#include <synch/waitq.h>
39
#include <synch/spinlock.h>
40
#include <synch/spinlock.h>
40
#include <arch/types.h>
41
#include <arch/types.h>
-
 
42
#include <ddi/device.h>
-
 
43
#include <ddi/irq.h>
-
 
44
#include <ddi/ddi.h>
-
 
45
#include <ipc/irq.h>
41
#include <arch.h>
46
#include <arch.h>
42
#include <func.h>
47
#include <func.h>
43
#include <print.h>
48
#include <print.h>
44
#include <atomic.h>
49
#include <atomic.h>
45
 
50
 
-
 
51
#define KLOG_SIZE PAGE_SIZE
46
#define BUFLEN 2048
52
#define KLOG_LATENCY 8
-
 
53
 
-
 
54
/** Kernel log cyclic buffer */
-
 
55
static char klog[KLOG_SIZE] __attribute__ ((aligned (PAGE_SIZE)));
-
 
56
 
-
 
57
/** Kernel log initialized */
47
static char debug_buffer[BUFLEN];
58
static bool klog_inited = false;
-
 
59
/** First kernel log characters */
-
 
60
static index_t klog_start = 0;
-
 
61
/** Number of valid kernel log characters */
48
static size_t offset = 0;
62
static size_t klog_len = 0;
-
 
63
/** Number of stored (not printed) kernel log characters */
-
 
64
static size_t klog_stored = 0;
49
/** Initialize stdout to something that does not print, but does not fail
65
/** Number of stored kernel log characters for uspace */
-
 
66
static size_t klog_uspace = 0;
-
 
67
 
-
 
68
/** Silence output */
-
 
69
bool silent = false;
50
 *
70
 
51
 * Save data in some buffer so that it could be retrieved in the debugger
71
/** Kernel log spinlock */
-
 
72
SPINLOCK_INITIALIZE(klog_lock);
52
 */
73
 
53
static void null_putchar(chardev_t *d, const char ch)
74
/** Physical memory area used for klog buffer */
-
 
75
static parea_t klog_parea;
54
{
76
 
-
 
77
/*
55
    if (offset >= BUFLEN)
78
 * For now, we use 0 as INR.
-
 
79
 * However, it is therefore desirable to have architecture specific
-
 
80
 * definition of KLOG_VIRT_INR in the future.
56
        offset = 0;
81
 */
57
    debug_buffer[offset++] = ch;
82
#define KLOG_VIRT_INR   0
58
}
83
 
-
 
84
static irq_t klog_irq;
59
 
85
 
60
static chardev_operations_t null_stdout_ops = {
86
static chardev_operations_t null_stdout_ops = {
-
 
87
    .suspend = NULL,
-
 
88
    .resume = NULL,
61
    .write = null_putchar
89
    .write = NULL,
-
 
90
    .read = NULL
62
};
91
};
63
 
92
 
64
chardev_t null_stdout = {
93
chardev_t null_stdout = {
65
    .name = "null",
94
    .name = "null",
66
    .op = &null_stdout_ops
95
    .op = &null_stdout_ops
67
};
96
};
68
 
97
 
-
 
98
/** Allways refuse IRQ ownership.
-
 
99
 *
-
 
100
 * This is not a real IRQ, so we always decline.
-
 
101
 *
-
 
102
 * @return Always returns IRQ_DECLINE.
-
 
103
 */
-
 
104
static irq_ownership_t klog_claim(irq_t *irq)
-
 
105
{
-
 
106
    return IRQ_DECLINE;
-
 
107
}
-
 
108
 
-
 
109
static void stdin_suspend(chardev_t *d)
-
 
110
{
-
 
111
}
-
 
112
 
-
 
113
static void stdin_resume(chardev_t *d)
-
 
114
{
-
 
115
}
-
 
116
 
-
 
117
static chardev_operations_t stdin_ops = {
-
 
118
    .suspend = stdin_suspend,
-
 
119
    .resume = stdin_resume,
-
 
120
};
-
 
121
 
69
/** Standard input character device. */
122
/** Standard input character device */
-
 
123
static chardev_t _stdin;
70
chardev_t *stdin = NULL;
124
chardev_t *stdin = NULL;
71
chardev_t *stdout = &null_stdout;
125
chardev_t *stdout = &null_stdout;
72
 
126
 
-
 
127
void console_init(void)
-
 
128
{
-
 
129
    chardev_initialize("stdin", &_stdin, &stdin_ops);
-
 
130
    stdin = &_stdin;
-
 
131
}
-
 
132
 
-
 
133
/** Initialize kernel logging facility
-
 
134
 *
-
 
135
 * The shared area contains kernel cyclic buffer. Userspace application may
-
 
136
 * be notified on new data with indication of position and size
-
 
137
 * of the data within the circular buffer.
-
 
138
 */
-
 
139
void klog_init(void)
-
 
140
{
-
 
141
    void *faddr = (void *) KA2PA(klog);
-
 
142
   
-
 
143
    ASSERT((uintptr_t) faddr % FRAME_SIZE == 0);
-
 
144
    ASSERT(KLOG_SIZE % FRAME_SIZE == 0);
-
 
145
 
-
 
146
    devno_t devno = device_assign_devno();
-
 
147
   
-
 
148
    klog_parea.pbase = (uintptr_t) faddr;
-
 
149
    klog_parea.frames = SIZE2FRAMES(KLOG_SIZE);
-
 
150
    ddi_parea_register(&klog_parea);
-
 
151
 
-
 
152
    sysinfo_set_item_val("klog.faddr", NULL, (unative_t) faddr);
-
 
153
    sysinfo_set_item_val("klog.pages", NULL, SIZE2FRAMES(KLOG_SIZE));
-
 
154
    sysinfo_set_item_val("klog.devno", NULL, devno);
-
 
155
    sysinfo_set_item_val("klog.inr", NULL, KLOG_VIRT_INR);
-
 
156
 
-
 
157
    irq_initialize(&klog_irq);
-
 
158
    klog_irq.devno = devno;
-
 
159
    klog_irq.inr = KLOG_VIRT_INR;
-
 
160
    klog_irq.claim = klog_claim;
-
 
161
    irq_register(&klog_irq);
-
 
162
   
-
 
163
    spinlock_lock(&klog_lock);
-
 
164
    klog_inited = true;
-
 
165
    spinlock_unlock(&klog_lock);
-
 
166
}
-
 
167
 
-
 
168
void grab_console(void)
-
 
169
{
-
 
170
    silent = false;
-
 
171
    arch_grab_console();
-
 
172
}
-
 
173
 
-
 
174
void release_console(void)
-
 
175
{
-
 
176
    silent = true;
-
 
177
    arch_release_console();
-
 
178
}
-
 
179
 
73
/** Get character from character device. Do not echo character.
180
/** Get character from character device. Do not echo character.
74
 *
181
 *
75
 * @param chardev Character device.
182
 * @param chardev Character device.
76
 *
183
 *
77
 * @return Character read.
184
 * @return Character read.
Line 88... Line 195...
88
         */
195
         */
89
        if (chardev->op->read)
196
        if (chardev->op->read)
90
            return chardev->op->read(chardev);
197
            return chardev->op->read(chardev);
91
        /* no other way of interacting with user, halt */
198
        /* no other way of interacting with user, halt */
92
        if (CPU)
199
        if (CPU)
93
            printf("cpu%d: ", CPU->id);
200
            printf("cpu%u: ", CPU->id);
94
        else
201
        else
95
            printf("cpu: ");
202
            printf("cpu: ");
96
        printf("halted - no kconsole\n");
203
        printf("halted (no kconsole)\n");
97
        cpu_halt();
204
        cpu_halt();
98
    }
205
    }
99
 
206
 
100
    waitq_sleep(&chardev->wq);
207
    waitq_sleep(&chardev->wq);
101
    ipl = interrupts_disable();
208
    ipl = interrupts_disable();
Line 123... Line 230...
123
 */
230
 */
124
count_t gets(chardev_t *chardev, char *buf, size_t buflen)
231
count_t gets(chardev_t *chardev, char *buf, size_t buflen)
125
{
232
{
126
    index_t index = 0;
233
    index_t index = 0;
127
    char ch;
234
    char ch;
128
 
235
   
129
    while (index < buflen) {
236
    while (index < buflen) {
130
        ch = _getc(chardev);
237
        ch = _getc(chardev);
131
        if (ch == '\b') {
238
        if (ch == '\b') {
132
            if (index > 0) {
239
            if (index > 0) {
133
                index--;
240
                index--;
Line 137... Line 244...
137
                putchar('\b');
244
                putchar('\b');
138
            }
245
            }
139
            continue;
246
            continue;
140
        }
247
        }
141
        putchar(ch);
248
        putchar(ch);
142
 
249
       
143
        if (ch == '\n') { /* end of string => write 0, return */
250
        if (ch == '\n') { /* end of string => write 0, return */
144
            buf[index] = '\0';
251
            buf[index] = '\0';
145
            return (count_t) index;
252
            return (count_t) index;
146
        }
253
        }
147
        buf[index++] = ch;
254
        buf[index++] = ch;
Line 157... Line 264...
157
    ch = _getc(chardev);
264
    ch = _getc(chardev);
158
    putchar(ch);
265
    putchar(ch);
159
    return ch;
266
    return ch;
160
}
267
}
161
 
268
 
-
 
269
void klog_update(void)
-
 
270
{
-
 
271
    spinlock_lock(&klog_lock);
-
 
272
   
-
 
273
    if ((klog_inited) && (klog_irq.notif_cfg.notify) && (klog_uspace > 0)) {
-
 
274
        ipc_irq_send_msg_3(&klog_irq, klog_start, klog_len, klog_uspace);
-
 
275
        klog_uspace = 0;
-
 
276
    }
-
 
277
   
-
 
278
    spinlock_unlock(&klog_lock);
-
 
279
}
-
 
280
 
162
void putchar(char c)
281
void putchar(char c)
163
{
282
{
-
 
283
    spinlock_lock(&klog_lock);
-
 
284
   
-
 
285
    if ((klog_stored > 0) && (stdout->op->write)) {
-
 
286
        /* Print charaters stored in kernel log */
-
 
287
        index_t i;
-
 
288
        for (i = klog_len - klog_stored; i < klog_len; i++)
-
 
289
            stdout->op->write(stdout, klog[(klog_start + i) % KLOG_SIZE], silent);
-
 
290
        klog_stored = 0;
-
 
291
    }
-
 
292
   
-
 
293
    /* Store character in the cyclic kernel log */
-
 
294
    klog[(klog_start + klog_len) % KLOG_SIZE] = c;
-
 
295
    if (klog_len < KLOG_SIZE)
-
 
296
        klog_len++;
-
 
297
    else
-
 
298
        klog_start = (klog_start + 1) % KLOG_SIZE;
-
 
299
   
164
    if (stdout->op->write)
300
    if (stdout->op->write)
165
        stdout->op->write(stdout, c);
301
        stdout->op->write(stdout, c, silent);
-
 
302
    else {
-
 
303
        /* The character is just in the kernel log */
-
 
304
        if (klog_stored < klog_len)
-
 
305
            klog_stored++;
-
 
306
    }
-
 
307
   
-
 
308
    /* The character is stored for uspace */
-
 
309
    if (klog_uspace < klog_len)
-
 
310
        klog_uspace++;
-
 
311
   
-
 
312
    /* Check notify uspace to update */
-
 
313
    bool update;
-
 
314
    if ((klog_uspace > KLOG_LATENCY) || (c == '\n'))
-
 
315
        update = true;
-
 
316
    else
-
 
317
        update = false;
-
 
318
   
-
 
319
    spinlock_unlock(&klog_lock);
-
 
320
   
-
 
321
    if (update)
-
 
322
        klog_update();
166
}
323
}
167
 
324
 
168
/** @}
325
/** @}
169
 */
326
 */