source: mainline/uspace/srv/console/console.c@ ccd1a14

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since ccd1a14 was ccd1a14, checked in by Jiri Svoboda <jirik.svoboda@…>, 16 years ago

Stop userspace kbd driver from polling when switching to kcon. Also, fix swapped reversed enabling/disabling of polling in kernel sgcn and ski drivers.

  • Property mode set to 100644
File size: 18.5 KB
Line 
1/*
2 * Copyright (c) 2006 Josef Cejka
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup console
30 * @{
31 */
32/** @file
33 */
34
35#include <libc.h>
36#include <fb.h>
37#include <ipc/ipc.h>
38#include <kbd.h>
39#include <kbd/keycode.h>
40#include <ipc/fb.h>
41#include <ipc/services.h>
42#include <errno.h>
43#include <key_buffer.h>
44#include <ipc/console.h>
45#include <unistd.h>
46#include <async.h>
47#include <libadt/fifo.h>
48#include <screenbuffer.h>
49#include <sys/mman.h>
50#include <stdio.h>
51#include <string.h>
52#include <sysinfo.h>
53#include <event.h>
54
55#include "console.h"
56#include "gcons.h"
57
58#define MAX_KEYREQUESTS_BUFFERED 32
59
60#define NAME "console"
61
62/** Index of currently used virtual console.
63 */
64int active_console = 0;
65int prev_console = 0;
66
67/** Phone to the keyboard driver. */
68static int kbd_phone;
69
70/** Information about framebuffer */
71struct {
72 int phone; /**< Framebuffer phone */
73 ipcarg_t rows; /**< Framebuffer rows */
74 ipcarg_t cols; /**< Framebuffer columns */
75} fb_info;
76
77typedef struct {
78 keybuffer_t keybuffer; /**< Buffer for incoming keys. */
79 /** Buffer for unsatisfied request for keys. */
80 FIFO_CREATE_STATIC(keyrequests, ipc_callid_t,
81 MAX_KEYREQUESTS_BUFFERED);
82 int keyrequest_counter; /**< Number of requests in buffer. */
83 int client_phone; /**< Phone to connected client. */
84 int used; /**< 1 if this virtual console is
85 * connected to some client.*/
86 screenbuffer_t screenbuffer; /**< Screenbuffer for saving screen
87 * contents and related settings. */
88} connection_t;
89
90static connection_t connections[CONSOLE_COUNT]; /**< Array of data for virtual
91 * consoles */
92static keyfield_t *interbuffer = NULL; /**< Pointer to memory shared
93 * with framebufer used for
94 * faster virtual console
95 * switching */
96
97/** Information on row-span yet unsent to FB driver. */
98struct {
99 int row; /**< Row where the span lies. */
100 int col; /**< Leftmost column of the span. */
101 int n; /**< Width of the span. */
102} fb_pending;
103
104/** Size of cwrite_buf. */
105#define CWRITE_BUF_SIZE 256
106
107/** Buffer for receiving data via the CONSOLE_WRITE call from the client. */
108static char cwrite_buf[CWRITE_BUF_SIZE];
109
110static void fb_putchar(wchar_t c, int row, int col);
111
112
113/** Find unused virtual console.
114 *
115 */
116static int find_free_connection(void)
117{
118 int i;
119
120 for (i = 0; i < CONSOLE_COUNT; i++) {
121 if (!connections[i].used)
122 return i;
123 }
124 return -1;
125}
126
127static void clrscr(void)
128{
129 async_msg_0(fb_info.phone, FB_CLEAR);
130}
131
132static void curs_visibility(bool visible)
133{
134 async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
135}
136
137static void curs_hide_sync(void)
138{
139 ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
140}
141
142static void curs_goto(int row, int col)
143{
144 async_msg_2(fb_info.phone, FB_CURSOR_GOTO, row, col);
145}
146
147static void screen_yield(void)
148{
149 ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
150}
151
152static void screen_reclaim(void)
153{
154 ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
155}
156
157static void kbd_yield(void)
158{
159 ipc_call_sync_0_0(kbd_phone, KBD_YIELD);
160}
161
162static void kbd_reclaim(void)
163{
164 ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM);
165}
166
167static void set_style(int style)
168{
169 async_msg_1(fb_info.phone, FB_SET_STYLE, style);
170}
171
172static void set_color(int fgcolor, int bgcolor, int flags)
173{
174 async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
175}
176
177static void set_rgb_color(int fgcolor, int bgcolor)
178{
179 async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
180}
181
182static void set_attrs(attrs_t *attrs)
183{
184 switch (attrs->t) {
185 case at_style:
186 set_style(attrs->a.s.style);
187 break;
188
189 case at_idx:
190 set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
191 attrs->a.i.flags);
192 break;
193
194 case at_rgb:
195 set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
196 break;
197 }
198}
199
200/** Send an area of screenbuffer to the FB driver. */
201static void fb_update_area(connection_t *conn, int x, int y, int w, int h)
202{
203 int i, j;
204 int rc;
205 attrs_t *attrs;
206 keyfield_t *field;
207
208 if (interbuffer) {
209 for (j = 0; j < h; j++) {
210 for (i = 0; i < w; i++) {
211 interbuffer[i + j * w] =
212 *get_field_at(&conn->screenbuffer,
213 x + i, y + j);
214 }
215 }
216
217 rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
218 x, y, w, h);
219 } else {
220 rc = ENOTSUP;
221 }
222
223 if (rc != 0) {
224 /*
225 attrs = &conn->screenbuffer.attrs;
226
227 for (j = 0; j < h; j++) {
228 for (i = 0; i < w; i++) {
229 field = get_field_at(&conn->screenbuffer,
230 x + i, y + j);
231 if (!attrs_same(*attrs, field->attrs))
232 set_attrs(&field->attrs);
233 attrs = &field->attrs;
234
235 fb_putchar(field->character, y + j, x + i);
236 }
237 }*/
238 }
239}
240
241/** Flush pending cells to FB. */
242static void fb_pending_flush(void)
243{
244 screenbuffer_t *scr;
245
246 scr = &(connections[active_console].screenbuffer);
247
248 if (fb_pending.n > 0) {
249 fb_update_area(&connections[active_console], fb_pending.col,
250 fb_pending.row, fb_pending.n, 1);
251 fb_pending.n = 0;
252 }
253}
254
255/** Mark a character cell as changed.
256 *
257 * This adds the cell to the pending rowspan if possible. Otherwise
258 * the old span is flushed first.
259 */
260static void cell_mark_changed(int row, int col)
261{
262 if (fb_pending.n != 0) {
263 if (row != fb_pending.row ||
264 col != fb_pending.col + fb_pending.n) {
265 fb_pending_flush();
266 }
267 }
268
269 if (fb_pending.n == 0) {
270 fb_pending.row = row;
271 fb_pending.col = col;
272 }
273
274 ++fb_pending.n;
275}
276
277
278/** Print a character to the active VC with buffering. */
279static void fb_putchar(wchar_t c, int row, int col)
280{
281 async_msg_3(fb_info.phone, FB_PUTCHAR, c, row, col);
282}
283
284/** Process a character from the client (TTY emulation). */
285static void write_char(int console, wchar_t ch)
286{
287 bool flush_cursor = false;
288 screenbuffer_t *scr = &(connections[console].screenbuffer);
289
290 switch (ch) {
291 case '\n':
292 fb_pending_flush();
293 flush_cursor = true;
294 scr->position_y++;
295 scr->position_x = 0;
296 break;
297 case '\r':
298 break;
299 case '\t':
300 scr->position_x += 8;
301 scr->position_x -= scr->position_x % 8;
302 break;
303 case '\b':
304 if (scr->position_x == 0)
305 break;
306 scr->position_x--;
307 if (console == active_console)
308 cell_mark_changed(scr->position_y, scr->position_x);
309 screenbuffer_putchar(scr, ' ');
310 break;
311 default:
312 if (console == active_console)
313 cell_mark_changed(scr->position_y, scr->position_x);
314
315 screenbuffer_putchar(scr, ch);
316 scr->position_x++;
317 }
318
319 if (scr->position_x >= scr->size_x) {
320 flush_cursor = true;
321 scr->position_y++;
322 }
323
324 if (scr->position_y >= scr->size_y) {
325 fb_pending_flush();
326 scr->position_y = scr->size_y - 1;
327 screenbuffer_clear_line(scr, scr->top_line);
328 scr->top_line = (scr->top_line + 1) % scr->size_y;
329 if (console == active_console)
330 async_msg_1(fb_info.phone, FB_SCROLL, 1);
331 }
332
333 scr->position_x = scr->position_x % scr->size_x;
334
335 if (console == active_console && flush_cursor)
336 curs_goto(scr->position_y, scr->position_x);
337}
338
339/** Switch to new console */
340static void change_console(int newcons)
341{
342 connection_t *conn;
343 int i, j, rc;
344 keyfield_t *field;
345 attrs_t *attrs;
346
347 if (newcons == active_console)
348 return;
349
350 fb_pending_flush();
351
352 if (newcons == KERNEL_CONSOLE) {
353 async_serialize_start();
354 curs_hide_sync();
355 gcons_in_kernel();
356 screen_yield();
357 kbd_yield();
358 async_serialize_end();
359
360
361 if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
362 prev_console = active_console;
363 active_console = KERNEL_CONSOLE;
364 } else
365 newcons = active_console;
366 }
367
368 if (newcons != KERNEL_CONSOLE) {
369 async_serialize_start();
370
371 if (active_console == KERNEL_CONSOLE) {
372 screen_reclaim();
373 kbd_reclaim();
374 gcons_redraw_console();
375 }
376
377 active_console = newcons;
378 gcons_change_console(newcons);
379 conn = &connections[active_console];
380
381 set_attrs(&conn->screenbuffer.attrs);
382 curs_visibility(false);
383 if (interbuffer) {
384 for (j = 0; j < conn->screenbuffer.size_y; j++) {
385 for (i = 0; i < conn->screenbuffer.size_x; i++) {
386 unsigned int size_x;
387
388 size_x = conn->screenbuffer.size_x;
389 interbuffer[j * size_x + i] =
390 *get_field_at(&conn->screenbuffer, i, j);
391 }
392 }
393 /* This call can preempt, but we are already at the end */
394 rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
395 0, 0, conn->screenbuffer.size_x,
396 conn->screenbuffer.size_y);
397 }
398
399 if ((!interbuffer) || (rc != 0)) {
400 set_attrs(&conn->screenbuffer.attrs);
401 clrscr();
402 attrs = &conn->screenbuffer.attrs;
403
404 for (j = 0; j < conn->screenbuffer.size_y; j++)
405 for (i = 0; i < conn->screenbuffer.size_x; i++) {
406 field = get_field_at(&conn->screenbuffer, i, j);
407 if (!attrs_same(*attrs, field->attrs))
408 set_attrs(&field->attrs);
409 attrs = &field->attrs;
410 if ((field->character == ' ') &&
411 (attrs_same(field->attrs,
412 conn->screenbuffer.attrs)))
413 continue;
414
415 fb_putchar(field->character, j, i);
416 }
417 }
418
419 curs_goto(conn->screenbuffer.position_y,
420 conn->screenbuffer.position_x);
421 curs_visibility(conn->screenbuffer.is_cursor_visible);
422
423 async_serialize_end();
424 }
425}
426
427/** Handler for keyboard */
428static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
429{
430 ipc_callid_t callid;
431 ipc_call_t call;
432 int retval;
433 kbd_event_t ev;
434 connection_t *conn;
435 int newcon;
436
437 /* Ignore parameters, the connection is alread opened */
438 while (1) {
439 callid = async_get_call(&call);
440 switch (IPC_GET_METHOD(call)) {
441 case IPC_M_PHONE_HUNGUP:
442 /* TODO: Handle hangup */
443 return;
444 case KBD_MS_LEFT:
445 newcon = gcons_mouse_btn(IPC_GET_ARG1(call));
446 if (newcon != -1)
447 change_console(newcon);
448 retval = 0;
449 break;
450 case KBD_MS_MOVE:
451 gcons_mouse_move(IPC_GET_ARG1(call),
452 IPC_GET_ARG2(call));
453 retval = 0;
454 break;
455 case KBD_EVENT:
456 /* Got event from keyboard driver. */
457 retval = 0;
458 ev.type = IPC_GET_ARG1(call);
459 ev.key = IPC_GET_ARG2(call);
460 ev.mods = IPC_GET_ARG3(call);
461 ev.c = IPC_GET_ARG4(call);
462
463 /* switch to another virtual console */
464
465 conn = &connections[active_console];
466
467 if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
468 CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
469 if (ev.key == KC_F12)
470 change_console(KERNEL_CONSOLE);
471 else
472 change_console(ev.key - KC_F1);
473 break;
474 }
475
476 /* if client is awaiting key, send it */
477 if (conn->keyrequest_counter > 0) {
478 conn->keyrequest_counter--;
479 ipc_answer_4(fifo_pop(conn->keyrequests), EOK,
480 ev.type, ev.key, ev.mods, ev.c);
481 break;
482 }
483
484 keybuffer_push(&conn->keybuffer, &ev);
485 retval = 0;
486
487 break;
488 default:
489 retval = ENOENT;
490 }
491 ipc_answer_0(callid, retval);
492 }
493}
494
495/** Handle CONSOLE_WRITE call. */
496static void cons_write(int consnum, ipc_callid_t rid, ipc_call_t *request)
497{
498 ipc_callid_t callid;
499 size_t size;
500 wchar_t ch;
501 size_t off;
502
503 if (!ipc_data_write_receive(&callid, &size)) {
504 ipc_answer_0(callid, EINVAL);
505 ipc_answer_0(rid, EINVAL);
506 }
507
508 if (size > CWRITE_BUF_SIZE)
509 size = CWRITE_BUF_SIZE;
510
511 (void) ipc_data_write_finalize(callid, cwrite_buf, size);
512
513 off = 0;
514 while (off < size) {
515 ch = str_decode(cwrite_buf, &off, size);
516 write_char(consnum, ch);
517 }
518
519 gcons_notify_char(consnum);
520 ipc_answer_1(rid, EOK, size);
521}
522
523/** Default thread for new connections */
524static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
525{
526 ipc_callid_t callid;
527 ipc_call_t call;
528 int consnum;
529 ipcarg_t arg1, arg2, arg3, arg4;
530 connection_t *conn;
531 screenbuffer_t *scr;
532
533 if ((consnum = find_free_connection()) == -1) {
534 ipc_answer_0(iid, ELIMIT);
535 return;
536 }
537 conn = &connections[consnum];
538 conn->used = 1;
539
540 async_serialize_start();
541 gcons_notify_connect(consnum);
542 conn->client_phone = IPC_GET_ARG5(*icall);
543 screenbuffer_clear(&conn->screenbuffer);
544 if (consnum == active_console)
545 clrscr();
546
547 /* Accept the connection */
548 ipc_answer_0(iid, EOK);
549
550 while (1) {
551 async_serialize_end();
552 callid = async_get_call(&call);
553 async_serialize_start();
554
555 arg1 = 0;
556 arg2 = 0;
557 arg3 = 0;
558 arg4 = 0;
559
560 switch (IPC_GET_METHOD(call)) {
561 case IPC_M_PHONE_HUNGUP:
562 gcons_notify_disconnect(consnum);
563
564 /* Answer all pending requests */
565 while (conn->keyrequest_counter > 0) {
566 conn->keyrequest_counter--;
567 ipc_answer_0(fifo_pop(conn->keyrequests),
568 ENOENT);
569 break;
570 }
571 conn->used = 0;
572 return;
573 case CONSOLE_PUTCHAR:
574 write_char(consnum, IPC_GET_ARG1(call));
575 gcons_notify_char(consnum);
576 break;
577 case CONSOLE_WRITE:
578 cons_write(consnum, callid, &call);
579 continue;
580 case CONSOLE_CLEAR:
581 /* Send message to fb */
582 if (consnum == active_console) {
583 async_msg_0(fb_info.phone, FB_CLEAR);
584 }
585
586 screenbuffer_clear(&conn->screenbuffer);
587
588 break;
589 case CONSOLE_GOTO:
590 screenbuffer_goto(&conn->screenbuffer,
591 IPC_GET_ARG2(call), IPC_GET_ARG1(call));
592 if (consnum == active_console)
593 curs_goto(IPC_GET_ARG1(call),
594 IPC_GET_ARG2(call));
595 break;
596 case CONSOLE_GETSIZE:
597 arg1 = fb_info.rows;
598 arg2 = fb_info.cols;
599 break;
600 case CONSOLE_FLUSH:
601 fb_pending_flush();
602 if (consnum == active_console) {
603 async_req_0_0(fb_info.phone, FB_FLUSH);
604
605 scr = &(connections[consnum].screenbuffer);
606 curs_goto(scr->position_y, scr->position_x);
607 }
608 break;
609 case CONSOLE_SET_STYLE:
610 fb_pending_flush();
611 arg1 = IPC_GET_ARG1(call);
612 screenbuffer_set_style(&conn->screenbuffer, arg1);
613 if (consnum == active_console)
614 set_style(arg1);
615 break;
616 case CONSOLE_SET_COLOR:
617 fb_pending_flush();
618 arg1 = IPC_GET_ARG1(call);
619 arg2 = IPC_GET_ARG2(call);
620 arg3 = IPC_GET_ARG3(call);
621 screenbuffer_set_color(&conn->screenbuffer, arg1,
622 arg2, arg3);
623 if (consnum == active_console)
624 set_color(arg1, arg2, arg3);
625 break;
626 case CONSOLE_SET_RGB_COLOR:
627 fb_pending_flush();
628 arg1 = IPC_GET_ARG1(call);
629 arg2 = IPC_GET_ARG2(call);
630 screenbuffer_set_rgb_color(&conn->screenbuffer, arg1,
631 arg2);
632 if (consnum == active_console)
633 set_rgb_color(arg1, arg2);
634 break;
635 case CONSOLE_CURSOR_VISIBILITY:
636 fb_pending_flush();
637 arg1 = IPC_GET_ARG1(call);
638 conn->screenbuffer.is_cursor_visible = arg1;
639 if (consnum == active_console)
640 curs_visibility(arg1);
641 break;
642 case CONSOLE_GETKEY:
643 if (keybuffer_empty(&conn->keybuffer)) {
644 /* buffer is empty -> store request */
645 if (conn->keyrequest_counter <
646 MAX_KEYREQUESTS_BUFFERED) {
647 fifo_push(conn->keyrequests, callid);
648 conn->keyrequest_counter++;
649 } else {
650 /*
651 * No key available and too many
652 * requests => fail.
653 */
654 ipc_answer_0(callid, ELIMIT);
655 }
656 continue;
657 }
658 kbd_event_t ev;
659 keybuffer_pop(&conn->keybuffer, &ev);
660 arg1 = ev.type;
661 arg2 = ev.key;
662 arg3 = ev.mods;
663 arg4 = ev.c;
664 break;
665 case CONSOLE_KCON_ENABLE:
666 change_console(KERNEL_CONSOLE);
667 break;
668 }
669 ipc_answer_4(callid, EOK, arg1, arg2, arg3, arg4);
670 }
671}
672
673static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
674{
675 change_console(prev_console);
676}
677
678int main(int argc, char *argv[])
679{
680 printf(NAME ": HelenOS Console service\n");
681
682 ipcarg_t phonehash;
683 size_t ib_size;
684 int i;
685
686 async_set_client_connection(client_connection);
687
688 /* Connect to keyboard driver */
689 kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
690 if (kbd_phone < 0) {
691 printf(NAME ": Failed to connect to keyboard service\n");
692 return -1;
693 }
694
695 if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
696 printf(NAME ": Failed to create callback from keyboard service\n");
697 return -1;
698 }
699
700 async_new_connection(phonehash, 0, NULL, keyboard_events);
701
702 /* Connect to framebuffer driver */
703 fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
704 if (fb_info.phone < 0) {
705 printf(NAME ": Failed to connect to video service\n");
706 return -1;
707 }
708
709 /* Disable kernel output to the console */
710 __SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
711
712 /* Initialize gcons */
713 gcons_init(fb_info.phone);
714 /* Synchronize, the gcons can have something in queue */
715 async_req_0_0(fb_info.phone, FB_FLUSH);
716
717 async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.rows,
718 &fb_info.cols);
719 set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
720 clrscr();
721
722 /* Init virtual consoles */
723 for (i = 0; i < CONSOLE_COUNT; i++) {
724 connections[i].used = 0;
725 keybuffer_init(&connections[i].keybuffer);
726
727 connections[i].keyrequests.head = 0;
728 connections[i].keyrequests.tail = 0;
729 connections[i].keyrequests.items = MAX_KEYREQUESTS_BUFFERED;
730 connections[i].keyrequest_counter = 0;
731
732 if (screenbuffer_init(&connections[i].screenbuffer,
733 fb_info.cols, fb_info.rows) == NULL) {
734 /* FIXME: handle error */
735 return -1;
736 }
737 }
738 connections[KERNEL_CONSOLE].used = 1;
739
740 /* Set up shared memory buffer. */
741 ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
742 interbuffer = as_get_mappable_page(ib_size);
743
744 fb_pending.n = 0;
745
746 if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
747 AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer) {
748 interbuffer = NULL;
749 }
750
751 if (interbuffer) {
752 if (ipc_share_out_start(fb_info.phone, interbuffer,
753 AS_AREA_READ) != EOK) {
754 as_area_destroy(interbuffer);
755 interbuffer = NULL;
756 }
757 }
758
759 curs_goto(0, 0);
760 curs_visibility(
761 connections[active_console].screenbuffer.is_cursor_visible);
762
763 /* Register at NS */
764 if (ipc_connect_to_me(PHONE_NS, SERVICE_CONSOLE, 0, 0, &phonehash) != 0)
765 return -1;
766
767 /* Receive kernel notifications */
768 if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
769 printf(NAME ": Error registering kconsole notifications\n");
770
771 async_set_interrupt_received(interrupt_received);
772
773 // FIXME: avoid connectiong to itself, keep using klog
774 // printf(NAME ": Accepting connections\n");
775 async_manager();
776
777 return 0;
778}
779
780/** @}
781 */
Note: See TracBrowser for help on using the repository browser.