Subversion Repositories HelenOS

Rev

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

Rev 4337 Rev 4338
Line 38... Line 38...
38
#include <keys.h>
38
#include <keys.h>
39
#include <ipc/fb.h>
39
#include <ipc/fb.h>
40
#include <ipc/services.h>
40
#include <ipc/services.h>
41
#include <errno.h>
41
#include <errno.h>
42
#include <key_buffer.h>
42
#include <key_buffer.h>
43
#include <console.h>
43
#include <ipc/console.h>
44
#include <unistd.h>
44
#include <unistd.h>
45
#include <async.h>
45
#include <async.h>
46
#include <libadt/fifo.h>
46
#include <libadt/fifo.h>
47
#include <screenbuffer.h>
47
#include <screenbuffer.h>
48
#include <sys/mman.h>
48
#include <sys/mman.h>
49
#include <stdio.h>
49
#include <stdio.h>
-
 
50
#include <sysinfo.h>
50
 
51
 
-
 
52
#include "console.h"
51
#include "gcons.h"
53
#include "gcons.h"
52
 
54
 
53
#define MAX_KEYREQUESTS_BUFFERED 32
55
#define MAX_KEYREQUESTS_BUFFERED 32
54
 
56
 
55
#define NAME "console"
57
#define NAME "console"
56
 
58
 
57
/** Index of currently used virtual console.
59
/** Index of currently used virtual console.
58
 */
60
 */
59
int active_console = 0;
61
int active_console = 0;
-
 
62
int prev_console = 0;
60
 
63
 
61
/** Information about framebuffer
64
/** Information about framebuffer
62
 */
65
 */
63
struct {
66
struct {
64
    int phone;      /**< Framebuffer phone */
67
    int phone;      /**< Framebuffer phone */
Line 119... Line 122...
119
static void curs_goto(int row, int col)
122
static void curs_goto(int row, int col)
120
{
123
{
121
    async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
124
    async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
122
}
125
}
123
 
126
 
124
static void set_style(style_t *style)
127
static void set_style(int style)
125
{
128
{
126
    async_msg_2(fb_info.phone, FB_SET_STYLE, style->fg_color,
129
    async_msg_1(fb_info.phone, FB_SET_STYLE, style);
127
        style->bg_color);
-
 
128
}
130
}
129
 
131
 
130
static void set_style_col(int fgcolor, int bgcolor)
132
static void set_color(int fgcolor, int bgcolor, int flags)
131
{
133
{
-
 
134
    async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
-
 
135
}
-
 
136
 
-
 
137
static void set_rgb_color(int fgcolor, int bgcolor)
-
 
138
{
132
    async_msg_2(fb_info.phone, FB_SET_STYLE, fgcolor, bgcolor);
139
    async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
-
 
140
}
-
 
141
 
-
 
142
static void set_attrs(attrs_t *attrs)
-
 
143
{
-
 
144
    switch (attrs->t) {
-
 
145
    case at_style:
-
 
146
        set_style(attrs->a.s.style);
-
 
147
        break;
-
 
148
 
-
 
149
    case at_idx:
-
 
150
        set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
-
 
151
            attrs->a.i.flags);
-
 
152
        break;
-
 
153
 
-
 
154
    case at_rgb:
-
 
155
        set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
-
 
156
        break;
-
 
157
    }
133
}
158
}
134
 
159
 
135
static void prtchr(char c, int row, int col)
160
static void prtchr(char c, int row, int col)
136
{
161
{
137
    async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
162
    async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
Line 193... Line 218...
193
static void change_console(int newcons)
218
static void change_console(int newcons)
194
{
219
{
195
    connection_t *conn;
220
    connection_t *conn;
196
    int i, j, rc;
221
    int i, j, rc;
197
    keyfield_t *field;
222
    keyfield_t *field;
198
    style_t *style;
223
    attrs_t *attrs;
199
   
224
   
200
    if (newcons == active_console)
225
    if (newcons == active_console)
201
        return;
226
        return;
202
   
227
   
203
    if (newcons == KERNEL_CONSOLE) {
228
    if (newcons == KERNEL_CONSOLE) {
204
        async_serialize_start();
229
        async_serialize_start();
205
        curs_hide_sync();
230
        curs_hide_sync();
206
        gcons_in_kernel();
231
        gcons_in_kernel();
207
        async_serialize_end();
232
        async_serialize_end();
208
       
233
       
209
        if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE))
234
        if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
-
 
235
            prev_console = active_console;
210
            active_console = KERNEL_CONSOLE;
236
            active_console = KERNEL_CONSOLE;
211
        else
237
        } else
212
            newcons = active_console;
238
            newcons = active_console;
213
    }
239
    }
214
   
240
   
215
    if (newcons != KERNEL_CONSOLE) {
241
    if (newcons != KERNEL_CONSOLE) {
216
        async_serialize_start();
242
        async_serialize_start();
Line 220... Line 246...
220
       
246
       
221
        active_console = newcons;
247
        active_console = newcons;
222
        gcons_change_console(newcons);
248
        gcons_change_console(newcons);
223
        conn = &connections[active_console];
249
        conn = &connections[active_console];
224
       
250
       
225
        set_style(&conn->screenbuffer.style);
251
        set_attrs(&conn->screenbuffer.attrs);
226
        curs_visibility(false);
252
        curs_visibility(false);
227
        if (interbuffer) {
253
        if (interbuffer) {
228
            for (i = 0; i < conn->screenbuffer.size_x; i++)
254
            for (i = 0; i < conn->screenbuffer.size_x; i++)
229
                for (j = 0; j < conn->screenbuffer.size_y; j++) {
255
                for (j = 0; j < conn->screenbuffer.size_y; j++) {
230
                    unsigned int size_x;
256
                    unsigned int size_x;
Line 232... Line 258...
232
                    size_x = conn->screenbuffer.size_x;
258
                    size_x = conn->screenbuffer.size_x;
233
                    interbuffer[i + j * size_x] =
259
                    interbuffer[i + j * size_x] =
234
                        *get_field_at(&conn->screenbuffer, i, j);
260
                        *get_field_at(&conn->screenbuffer, i, j);
235
                }
261
                }
236
            /* This call can preempt, but we are already at the end */
262
            /* This call can preempt, but we are already at the end */
237
            rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA);      
263
            rc = async_req_0_0(fb_info.phone, FB_DRAW_TEXT_DATA);
238
        }
264
        }
239
       
265
       
240
        if ((!interbuffer) || (rc != 0)) {
266
        if ((!interbuffer) || (rc != 0)) {
241
            set_style(&conn->screenbuffer.style);
267
            set_attrs(&conn->screenbuffer.attrs);
242
            clrscr();
268
            clrscr();
243
            style = &conn->screenbuffer.style;
269
            attrs = &conn->screenbuffer.attrs;
244
           
270
           
245
            for (j = 0; j < conn->screenbuffer.size_y; j++)
271
            for (j = 0; j < conn->screenbuffer.size_y; j++)
246
                for (i = 0; i < conn->screenbuffer.size_x; i++) {
272
                for (i = 0; i < conn->screenbuffer.size_x; i++) {
247
                    field = get_field_at(&conn->screenbuffer, i, j);
273
                    field = get_field_at(&conn->screenbuffer, i, j);
248
                    if (!style_same(*style, field->style))
274
                    if (!attrs_same(*attrs, field->attrs))
249
                        set_style(&field->style);
275
                        set_attrs(&field->attrs);
250
                    style = &field->style;
276
                    attrs = &field->attrs;
251
                    if ((field->character == ' ') &&
277
                    if ((field->character == ' ') &&
252
                        (style_same(field->style,
278
                        (attrs_same(field->attrs,
253
                        conn->screenbuffer.style)))
279
                        conn->screenbuffer.attrs)))
254
                        continue;
280
                        continue;
255
                   
281
 
256
                    prtchr(field->character, j, i);
282
                    prtchr(field->character, j, i);
257
                }
283
                }
258
        }
284
        }
259
       
285
       
260
        curs_goto(conn->screenbuffer.position_y,
286
        curs_goto(conn->screenbuffer.position_y,
Line 335... Line 361...
335
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
361
static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
336
{
362
{
337
    ipc_callid_t callid;
363
    ipc_callid_t callid;
338
    ipc_call_t call;
364
    ipc_call_t call;
339
    int consnum;
365
    int consnum;
340
    ipcarg_t arg1, arg2;
366
    ipcarg_t arg1, arg2, arg3;
341
    connection_t *conn;
367
    connection_t *conn;
342
 
368
   
343
    if ((consnum = find_free_connection()) == -1) {
369
    if ((consnum = find_free_connection()) == -1) {
344
        ipc_answer_0(iid, ELIMIT);
370
        ipc_answer_0(iid, ELIMIT);
345
        return;
371
        return;
346
    }
372
    }
347
    conn = &connections[consnum];
373
    conn = &connections[consnum];
Line 352... Line 378...
352
    conn->client_phone = IPC_GET_ARG5(*icall);
378
    conn->client_phone = IPC_GET_ARG5(*icall);
353
    screenbuffer_clear(&conn->screenbuffer);
379
    screenbuffer_clear(&conn->screenbuffer);
354
   
380
   
355
    /* Accept the connection */
381
    /* Accept the connection */
356
    ipc_answer_0(iid, EOK);
382
    ipc_answer_0(iid, EOK);
357
 
383
   
358
    while (1) {
384
    while (1) {
359
        async_serialize_end();
385
        async_serialize_end();
360
        callid = async_get_call(&call);
386
        callid = async_get_call(&call);
361
        async_serialize_start();
387
        async_serialize_start();
362
 
388
       
363
        arg1 = 0;
389
        arg1 = 0;
364
        arg2 = 0;
390
        arg2 = 0;
365
        switch (IPC_GET_METHOD(call)) {
391
        switch (IPC_GET_METHOD(call)) {
366
        case IPC_M_PHONE_HUNGUP:
392
        case IPC_M_PHONE_HUNGUP:
367
            gcons_notify_disconnect(consnum);
393
            gcons_notify_disconnect(consnum);
368
           
394
           
369
            /* Answer all pending requests */
395
            /* Answer all pending requests */
370
            while (conn->keyrequest_counter > 0) {     
396
            while (conn->keyrequest_counter > 0) {
371
                conn->keyrequest_counter--;
397
                conn->keyrequest_counter--;
372
                ipc_answer_0(fifo_pop(conn->keyrequests),
398
                ipc_answer_0(fifo_pop(conn->keyrequests),
373
                    ENOENT);
399
                    ENOENT);
374
                break;
400
                break;
375
            }
401
            }
Line 403... Line 429...
403
            if (consnum == active_console)
429
            if (consnum == active_console)
404
                async_req_0_0(fb_info.phone, FB_FLUSH);
430
                async_req_0_0(fb_info.phone, FB_FLUSH);
405
            break;
431
            break;
406
        case CONSOLE_SET_STYLE:
432
        case CONSOLE_SET_STYLE:
407
            arg1 = IPC_GET_ARG1(call);
433
            arg1 = IPC_GET_ARG1(call);
-
 
434
            screenbuffer_set_style(&conn->screenbuffer, arg1);
-
 
435
            if (consnum == active_console)
-
 
436
                set_style(arg1);
-
 
437
            break;
-
 
438
        case CONSOLE_SET_COLOR:
-
 
439
            arg1 = IPC_GET_ARG1(call);
-
 
440
            arg2 = IPC_GET_ARG2(call);
-
 
441
            arg3 = IPC_GET_ARG3(call);
-
 
442
            screenbuffer_set_color(&conn->screenbuffer, arg1,
-
 
443
                arg2, arg3);
-
 
444
            if (consnum == active_console)
-
 
445
                set_color(arg1, arg2, arg3);
-
 
446
            break;
-
 
447
        case CONSOLE_SET_RGB_COLOR:
-
 
448
            arg1 = IPC_GET_ARG1(call);
408
            arg2 = IPC_GET_ARG2(call);
449
            arg2 = IPC_GET_ARG2(call);
409
            screenbuffer_set_style(&conn->screenbuffer, arg1,
450
            screenbuffer_set_rgb_color(&conn->screenbuffer, arg1,
410
                arg2);
451
                arg2);
411
            if (consnum == active_console)
452
            if (consnum == active_console)
412
                set_style_col(arg1, arg2);
453
                set_rgb_color(arg1, arg2);
413
            break;
454
            break;
414
        case CONSOLE_CURSOR_VISIBILITY:
455
        case CONSOLE_CURSOR_VISIBILITY:
415
            arg1 = IPC_GET_ARG1(call);
456
            arg1 = IPC_GET_ARG1(call);
416
            conn->screenbuffer.is_cursor_visible = arg1;
457
            conn->screenbuffer.is_cursor_visible = arg1;
417
            if (consnum == active_console)
458
            if (consnum == active_console)
Line 440... Line 481...
440
        }
481
        }
441
        ipc_answer_2(callid, EOK, arg1, arg2);
482
        ipc_answer_2(callid, EOK, arg1, arg2);
442
    }
483
    }
443
}
484
}
444
 
485
 
-
 
486
static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
-
 
487
{
-
 
488
    change_console(prev_console);
-
 
489
}
-
 
490
 
445
int main(int argc, char *argv[])
491
int main(int argc, char *argv[])
446
{
492
{
447
    printf(NAME ": HelenOS Console service\n");
493
    printf(NAME ": HelenOS Console service\n");
448
   
494
   
449
    ipcarg_t phonehash;
495
    ipcarg_t phonehash;
450
    int kbd_phone;
496
    int kbd_phone;
451
    int i;
497
    int i;
452
 
498
   
453
    async_set_client_connection(client_connection);
499
    async_set_client_connection(client_connection);
454
   
500
   
455
    /* Connect to keyboard driver */
501
    /* Connect to keyboard driver */
456
 
502
   
457
    kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
503
    kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
458
    while (kbd_phone < 0) {
504
    while (kbd_phone < 0) {
459
        usleep(10000);
505
        usleep(10000);
460
        kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
506
        kbd_phone = ipc_connect_me_to(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
461
    }
507
    }
Line 476... Line 522...
476
    /* Synchronize, the gcons can have something in queue */
522
    /* Synchronize, the gcons can have something in queue */
477
    async_req_0_0(fb_info.phone, FB_FLUSH);
523
    async_req_0_0(fb_info.phone, FB_FLUSH);
478
   
524
   
479
    async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
525
    async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
480
        &fb_info.cols);
526
        &fb_info.cols);
481
    set_style_col(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
527
    set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
482
    clrscr();
528
    clrscr();
483
   
529
   
484
    /* Init virtual consoles */
530
    /* Init virtual consoles */
485
    for (i = 0; i < CONSOLE_COUNT; i++) {
531
    for (i = 0; i < CONSOLE_COUNT; i++) {
486
        connections[i].used = 0;
532
        connections[i].used = 0;
Line 508... Line 554...
508
            munmap(interbuffer,
554
            munmap(interbuffer,
509
                sizeof(keyfield_t) * fb_info.cols * fb_info.rows);
555
                sizeof(keyfield_t) * fb_info.cols * fb_info.rows);
510
            interbuffer = NULL;
556
            interbuffer = NULL;
511
        }
557
        }
512
    }
558
    }
513
 
559
   
514
    curs_goto(0, 0);
560
    curs_goto(0, 0);
515
    curs_visibility(
561
    curs_visibility(
516
        connections[active_console].screenbuffer.is_cursor_visible);
562
        connections[active_console].screenbuffer.is_cursor_visible);
517
 
563
   
518
    /* Register at NS */
564
    /* Register at NS */
519
    if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
565
    if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
520
        return -1;
566
        return -1;
521
   
567
   
-
 
568
    /* Receive kernel notifications */
-
 
569
    if (sysinfo_value("kconsole.present")) {
-
 
570
        int devno = sysinfo_value("kconsole.devno");
-
 
571
        int inr = sysinfo_value("kconsole.inr");
-
 
572
        if (ipc_register_irq(inr, devno, 0, NULL) != EOK)
-
 
573
            printf(NAME ": Error registering kconsole notifications\n");
-
 
574
       
-
 
575
        async_set_interrupt_received(interrupt_received);
-
 
576
    }
-
 
577
   
522
    // FIXME: avoid connectiong to itself, keep using klog
578
    // FIXME: avoid connectiong to itself, keep using klog
523
    // printf(NAME ": Accepting connections\n");
579
    // printf(NAME ": Accepting connections\n");
524
    async_manager();
580
    async_manager();
525
 
581
   
526
    return 0;  
582
    return 0;
527
}
583
}
528
 
584
 
529
/** @}
585
/** @}
530
 */
586
 */