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

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since c8b9f88 was c8b9f88, checked in by Martin Decky <martin@…>, 16 years ago

add forgotten answer in case of an error

  • Property mode set to 100644
File size: 19.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 <io/keycode.h>
40#include <ipc/fb.h>
41#include <ipc/services.h>
42#include <errno.h>
43#include <keybuffer.h>
44#include <ipc/console.h>
45#include <unistd.h>
46#include <async.h>
47#include <libadt/fifo.h>
48#include <sys/mman.h>
49#include <stdio.h>
50#include <string.h>
51#include <sysinfo.h>
52#include <event.h>
53#include <devmap.h>
54
55#include "console.h"
56#include "gcons.h"
57#include "screenbuffer.h"
58
59#define NAME "console"
60
61#define MAX_DEVICE_NAME 32
62
63/** Phone to the keyboard driver. */
64static int kbd_phone;
65
66/** Information about framebuffer */
67struct {
68 int phone; /**< Framebuffer phone */
69 ipcarg_t cols; /**< Framebuffer columns */
70 ipcarg_t rows; /**< Framebuffer rows */
71} fb_info;
72
73typedef struct {
74 size_t index; /**< Console index */
75 size_t refcount; /**< Connection reference count */
76 dev_handle_t dev_handle; /**< Device handle */
77 keybuffer_t keybuffer; /**< Buffer for incoming keys. */
78 screenbuffer_t scr; /**< Screenbuffer for saving screen
79 contents and related settings. */
80} console_t;
81
82/** Array of data for virtual consoles */
83static console_t consoles[CONSOLE_COUNT];
84
85static console_t *active_console = &consoles[0];
86static console_t *prev_console = &consoles[0];
87static console_t *kernel_console = &consoles[KERNEL_CONSOLE];
88
89/** Pointer to memory shared with framebufer used for
90 faster virtual console switching */
91static keyfield_t *interbuffer = NULL;
92
93/** Information on row-span yet unsent to FB driver. */
94struct {
95 size_t col; /**< Leftmost column of the span. */
96 size_t row; /**< Row where the span lies. */
97 size_t cnt; /**< Width of the span. */
98} fb_pending;
99
100/** Pending input structure. */
101typedef struct {
102 link_t link;
103 console_t *cons; /**< Console waiting for input */
104 ipc_callid_t rid; /**< Call ID waiting for input */
105 ipc_callid_t callid; /**< Call ID waiting for IPC_DATA_READ */
106
107 size_t pos; /**< Position of the last stored data */
108 size_t size; /**< Size of ther buffer */
109 char *data; /**< Already stored data */
110} pending_input_t;
111
112LIST_INITIALIZE(pending_input);
113
114/** Process pending input requests */
115static void process_pending_input(void)
116{
117 async_serialize_start();
118
119 link_t *cur;
120
121loop:
122 for (cur = pending_input.next; cur != &pending_input; cur = cur->next) {
123 pending_input_t *pr = list_get_instance(cur, pending_input_t, link);
124
125 console_event_t ev;
126 if (keybuffer_pop(&pr->cons->keybuffer, &ev)) {
127
128 if (pr->data != NULL) {
129 if (ev.type == KEY_PRESS) {
130 pr->data[pr->pos] = ev.c;
131 pr->pos++;
132 }
133 } else {
134 ipc_answer_4(pr->rid, EOK, ev.type, ev.key, ev.mods, ev.c);
135
136 list_remove(cur);
137 free(pr);
138
139 goto loop;
140 }
141 }
142
143 if ((pr->data != NULL) && (pr->pos == pr->size)) {
144 (void) ipc_data_read_finalize(pr->callid, pr->data, pr->size);
145 ipc_answer_1(pr->rid, EOK, pr->size);
146
147 free(pr->data);
148 list_remove(cur);
149 free(pr);
150
151 goto loop;
152 }
153 }
154
155 async_serialize_end();
156}
157
158static void curs_visibility(bool visible)
159{
160 async_msg_1(fb_info.phone, FB_CURSOR_VISIBILITY, visible);
161}
162
163static void curs_hide_sync(void)
164{
165 ipc_call_sync_1_0(fb_info.phone, FB_CURSOR_VISIBILITY, false);
166}
167
168static void curs_goto(size_t x, size_t y)
169{
170 async_msg_2(fb_info.phone, FB_CURSOR_GOTO, x, y);
171}
172
173static void screen_clear(void)
174{
175 async_msg_0(fb_info.phone, FB_CLEAR);
176}
177
178static void screen_yield(void)
179{
180 ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_YIELD);
181}
182
183static void screen_reclaim(void)
184{
185 ipc_call_sync_0_0(fb_info.phone, FB_SCREEN_RECLAIM);
186}
187
188static void kbd_yield(void)
189{
190 ipc_call_sync_0_0(kbd_phone, KBD_YIELD);
191}
192
193static void kbd_reclaim(void)
194{
195 ipc_call_sync_0_0(kbd_phone, KBD_RECLAIM);
196}
197
198static void set_style(int style)
199{
200 async_msg_1(fb_info.phone, FB_SET_STYLE, style);
201}
202
203static void set_color(int fgcolor, int bgcolor, int flags)
204{
205 async_msg_3(fb_info.phone, FB_SET_COLOR, fgcolor, bgcolor, flags);
206}
207
208static void set_rgb_color(int fgcolor, int bgcolor)
209{
210 async_msg_2(fb_info.phone, FB_SET_RGB_COLOR, fgcolor, bgcolor);
211}
212
213static void set_attrs(attrs_t *attrs)
214{
215 switch (attrs->t) {
216 case at_style:
217 set_style(attrs->a.s.style);
218 break;
219 case at_idx:
220 set_color(attrs->a.i.fg_color, attrs->a.i.bg_color,
221 attrs->a.i.flags);
222 break;
223 case at_rgb:
224 set_rgb_color(attrs->a.r.fg_color, attrs->a.r.bg_color);
225 break;
226 }
227}
228
229/** Send an area of screenbuffer to the FB driver. */
230static void fb_update_area(console_t *cons, ipcarg_t x0, ipcarg_t y0, ipcarg_t width, ipcarg_t height)
231{
232 if (interbuffer) {
233 ipcarg_t x;
234 ipcarg_t y;
235
236 for (y = 0; y < height; y++) {
237 for (x = 0; x < width; x++) {
238 interbuffer[y * width + x] =
239 *get_field_at(&cons->scr, x0 + x, y0 + y);
240 }
241 }
242
243 async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
244 x0, y0, width, height);
245 }
246}
247
248/** Flush pending cells to FB. */
249static void fb_pending_flush(void)
250{
251 if (fb_pending.cnt > 0) {
252 fb_update_area(active_console, fb_pending.col,
253 fb_pending.row, fb_pending.cnt, 1);
254 fb_pending.cnt = 0;
255 }
256}
257
258/** Mark a character cell as changed.
259 *
260 * This adds the cell to the pending rowspan if possible. Otherwise
261 * the old span is flushed first.
262 *
263 */
264static void cell_mark_changed(size_t col, size_t row)
265{
266 if (fb_pending.cnt != 0) {
267 if ((col != fb_pending.col + fb_pending.cnt)
268 || (row != fb_pending.row)) {
269 fb_pending_flush();
270 }
271 }
272
273 if (fb_pending.cnt == 0) {
274 fb_pending.col = col;
275 fb_pending.row = row;
276 }
277
278 fb_pending.cnt++;
279}
280
281/** Print a character to the active VC with buffering. */
282static void fb_putchar(wchar_t c, ipcarg_t col, ipcarg_t row)
283{
284 async_msg_3(fb_info.phone, FB_PUTCHAR, c, col, row);
285}
286
287/** Process a character from the client (TTY emulation). */
288static void write_char(console_t *cons, wchar_t ch)
289{
290 switch (ch) {
291 case '\n':
292 fb_pending_flush();
293 cons->scr.position_y++;
294 cons->scr.position_x = 0;
295 break;
296 case '\r':
297 break;
298 case '\t':
299 cons->scr.position_x += 8;
300 cons->scr.position_x -= cons->scr.position_x % 8;
301 break;
302 case '\b':
303 if (cons->scr.position_x == 0)
304 break;
305 cons->scr.position_x--;
306 if (cons == active_console)
307 cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
308 screenbuffer_putchar(&cons->scr, ' ');
309 break;
310 default:
311 if (cons == active_console)
312 cell_mark_changed(cons->scr.position_x, cons->scr.position_y);
313
314 screenbuffer_putchar(&cons->scr, ch);
315 cons->scr.position_x++;
316 }
317
318 if (cons->scr.position_x >= cons->scr.size_x)
319 cons->scr.position_y++;
320
321 if (cons->scr.position_y >= cons->scr.size_y) {
322 fb_pending_flush();
323 cons->scr.position_y = cons->scr.size_y - 1;
324 screenbuffer_clear_line(&cons->scr, cons->scr.top_line);
325 cons->scr.top_line = (cons->scr.top_line + 1) % cons->scr.size_y;
326
327 if (cons == active_console)
328 async_msg_1(fb_info.phone, FB_SCROLL, 1);
329 }
330
331 cons->scr.position_x = cons->scr.position_x % cons->scr.size_x;
332}
333
334/** Switch to new console */
335static void change_console(console_t *cons)
336{
337 if (cons == active_console)
338 return;
339
340 fb_pending_flush();
341
342 if (cons == kernel_console) {
343 async_serialize_start();
344 curs_hide_sync();
345 gcons_in_kernel();
346 screen_yield();
347 kbd_yield();
348 async_serialize_end();
349
350 if (__SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE)) {
351 prev_console = active_console;
352 active_console = kernel_console;
353 } else
354 cons = active_console;
355 }
356
357 if (cons != kernel_console) {
358 size_t x;
359 size_t y;
360 int rc = 0;
361
362 async_serialize_start();
363
364 if (active_console == kernel_console) {
365 screen_reclaim();
366 kbd_reclaim();
367 gcons_redraw_console();
368 }
369
370 active_console = cons;
371 gcons_change_console(cons->index);
372
373 set_attrs(&cons->scr.attrs);
374 curs_visibility(false);
375 if (interbuffer) {
376 for (y = 0; y < cons->scr.size_y; y++) {
377 for (x = 0; x < cons->scr.size_x; x++) {
378 interbuffer[y * cons->scr.size_x + x] =
379 *get_field_at(&cons->scr, x, y);
380 }
381 }
382
383 /* This call can preempt, but we are already at the end */
384 rc = async_req_4_0(fb_info.phone, FB_DRAW_TEXT_DATA,
385 0, 0, cons->scr.size_x,
386 cons->scr.size_y);
387 }
388
389 if ((!interbuffer) || (rc != 0)) {
390 set_attrs(&cons->scr.attrs);
391 screen_clear();
392
393 for (y = 0; y < cons->scr.size_y; y++)
394 for (x = 0; x < cons->scr.size_x; x++) {
395 keyfield_t *field = get_field_at(&cons->scr, x, y);
396
397 if (!attrs_same(cons->scr.attrs, field->attrs))
398 set_attrs(&field->attrs);
399
400 cons->scr.attrs = field->attrs;
401 if ((field->character == ' ') &&
402 (attrs_same(field->attrs, cons->scr.attrs)))
403 continue;
404
405 fb_putchar(field->character, x, y);
406 }
407 }
408
409 curs_goto(cons->scr.position_x, cons->scr.position_y);
410 curs_visibility(cons->scr.is_cursor_visible);
411
412 async_serialize_end();
413 }
414}
415
416/** Handler for keyboard */
417static void keyboard_events(ipc_callid_t iid, ipc_call_t *icall)
418{
419 /* Ignore parameters, the connection is already opened */
420 while (true) {
421
422 ipc_call_t call;
423 ipc_callid_t callid = async_get_call(&call);
424
425 int retval;
426 console_event_t ev;
427
428 switch (IPC_GET_METHOD(call)) {
429 case IPC_M_PHONE_HUNGUP:
430 /* TODO: Handle hangup */
431 return;
432 case KBD_EVENT:
433 /* Got event from keyboard driver. */
434 retval = 0;
435 ev.type = IPC_GET_ARG1(call);
436 ev.key = IPC_GET_ARG2(call);
437 ev.mods = IPC_GET_ARG3(call);
438 ev.c = IPC_GET_ARG4(call);
439
440 if ((ev.key >= KC_F1) && (ev.key < KC_F1 +
441 CONSOLE_COUNT) && ((ev.mods & KM_CTRL) == 0)) {
442 if (ev.key == KC_F1 + KERNEL_CONSOLE)
443 change_console(kernel_console);
444 else
445 change_console(&consoles[ev.key - KC_F1]);
446 break;
447 }
448
449 keybuffer_push(&active_console->keybuffer, &ev);
450 break;
451 default:
452 retval = ENOENT;
453 }
454 ipc_answer_0(callid, retval);
455 }
456}
457
458static void cons_write(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
459{
460 ipc_callid_t callid;
461 size_t size;
462 if (!ipc_data_write_receive(&callid, &size)) {
463 ipc_answer_0(callid, EINVAL);
464 ipc_answer_0(rid, EINVAL);
465 return;
466 }
467
468 char *buf = (char *) malloc(size);
469 if (buf == NULL) {
470 ipc_answer_0(callid, ENOMEM);
471 ipc_answer_0(rid, ENOMEM);
472 return;
473 }
474
475 (void) ipc_data_write_finalize(callid, buf, size);
476
477 async_serialize_start();
478
479 size_t off = 0;
480 while (off < size) {
481 wchar_t ch = str_decode(buf, &off, size);
482 write_char(cons, ch);
483 }
484
485 if (cons == active_console)
486 curs_goto(cons->scr.position_x, cons->scr.position_y);
487
488 async_serialize_end();
489
490 gcons_notify_char(cons->index);
491 ipc_answer_1(rid, EOK, size);
492
493 free(buf);
494}
495
496static void cons_read(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
497{
498 ipc_callid_t callid;
499 size_t size;
500 if (!ipc_data_read_receive(&callid, &size)) {
501 ipc_answer_0(callid, EINVAL);
502 ipc_answer_0(rid, EINVAL);
503 return;
504 }
505
506 char *buf = (char *) malloc(size);
507 if (buf == NULL) {
508 ipc_answer_0(callid, ENOMEM);
509 ipc_answer_0(rid, ENOMEM);
510 return;
511 }
512
513 async_serialize_start();
514
515 size_t pos = 0;
516 console_event_t ev;
517 while ((keybuffer_pop(&cons->keybuffer, &ev)) && (pos < size)) {
518 if (ev.type == KEY_PRESS) {
519 buf[pos] = ev.c;
520 pos++;
521 }
522 }
523
524 if (pos == size) {
525 (void) ipc_data_read_finalize(callid, buf, size);
526 ipc_answer_1(rid, EOK, size);
527 free(buf);
528 } else {
529 pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
530 if (!pr) {
531 ipc_answer_0(callid, ENOMEM);
532 ipc_answer_0(rid, ENOMEM);
533 free(buf);
534 async_serialize_end();
535 return;
536 }
537
538 pr->cons = cons;
539 pr->rid = rid;
540 pr->callid = callid;
541 pr->pos = pos;
542 pr->size = size;
543 pr->data = buf;
544 list_append(&pr->link, &pending_input);
545 }
546
547 async_serialize_end();
548}
549
550static void cons_get_event(console_t *cons, ipc_callid_t rid, ipc_call_t *request)
551{
552 async_serialize_start();
553
554 console_event_t ev;
555 if (keybuffer_pop(&cons->keybuffer, &ev)) {
556 ipc_answer_4(rid, EOK, ev.type, ev.key, ev.mods, ev.c);
557 } else {
558 pending_input_t *pr = (pending_input_t *) malloc(sizeof(pending_input_t));
559 if (!pr) {
560 ipc_answer_0(rid, ENOMEM);
561 async_serialize_end();
562 return;
563 }
564
565 pr->cons = cons;
566 pr->rid = rid;
567 pr->callid = 0;
568 pr->data = NULL;
569 list_append(&pr->link, &pending_input);
570 }
571
572 async_serialize_end();
573}
574
575/** Default thread for new connections */
576static void client_connection(ipc_callid_t iid, ipc_call_t *icall)
577{
578 console_t *cons = NULL;
579
580 size_t i;
581 for (i = 0; i < CONSOLE_COUNT; i++) {
582 if (i == KERNEL_CONSOLE)
583 continue;
584
585 if (consoles[i].dev_handle == (dev_handle_t) IPC_GET_ARG1(*icall)) {
586 cons = &consoles[i];
587 break;
588 }
589 }
590
591 if (cons == NULL) {
592 ipc_answer_0(iid, ENOENT);
593 return;
594 }
595
596 ipc_callid_t callid;
597 ipc_call_t call;
598 ipcarg_t arg1;
599 ipcarg_t arg2;
600 ipcarg_t arg3;
601
602 async_serialize_start();
603 if (cons->refcount == 0)
604 gcons_notify_connect(cons->index);
605
606 cons->refcount++;
607
608 /* Accept the connection */
609 ipc_answer_0(iid, EOK);
610
611 while (true) {
612 async_serialize_end();
613 callid = async_get_call(&call);
614 async_serialize_start();
615
616 arg1 = 0;
617 arg2 = 0;
618 arg3 = 0;
619
620 switch (IPC_GET_METHOD(call)) {
621 case IPC_M_PHONE_HUNGUP:
622 cons->refcount--;
623 if (cons->refcount == 0)
624 gcons_notify_disconnect(cons->index);
625 return;
626 case VFS_READ:
627 async_serialize_end();
628 cons_read(cons, callid, &call);
629 async_serialize_start();
630 continue;
631 case VFS_WRITE:
632 async_serialize_end();
633 cons_write(cons, callid, &call);
634 async_serialize_start();
635 continue;
636 case VFS_SYNC:
637 fb_pending_flush();
638 if (cons == active_console) {
639 async_req_0_0(fb_info.phone, FB_FLUSH);
640
641 curs_goto(cons->scr.position_x, cons->scr.position_y);
642 }
643 break;
644 case CONSOLE_CLEAR:
645 /* Send message to fb */
646 if (cons == active_console)
647 async_msg_0(fb_info.phone, FB_CLEAR);
648
649 screenbuffer_clear(&cons->scr);
650
651 break;
652 case CONSOLE_GOTO:
653 screenbuffer_goto(&cons->scr,
654 IPC_GET_ARG1(call), IPC_GET_ARG2(call));
655 if (cons == active_console)
656 curs_goto(IPC_GET_ARG1(call),
657 IPC_GET_ARG2(call));
658 break;
659 case CONSOLE_GET_SIZE:
660 arg1 = fb_info.cols;
661 arg2 = fb_info.rows;
662 break;
663 case CONSOLE_SET_STYLE:
664 fb_pending_flush();
665 arg1 = IPC_GET_ARG1(call);
666 screenbuffer_set_style(&cons->scr, arg1);
667 if (cons == active_console)
668 set_style(arg1);
669 break;
670 case CONSOLE_SET_COLOR:
671 fb_pending_flush();
672 arg1 = IPC_GET_ARG1(call);
673 arg2 = IPC_GET_ARG2(call);
674 arg3 = IPC_GET_ARG3(call);
675 screenbuffer_set_color(&cons->scr, arg1, arg2, arg3);
676 if (cons == active_console)
677 set_color(arg1, arg2, arg3);
678 break;
679 case CONSOLE_SET_RGB_COLOR:
680 fb_pending_flush();
681 arg1 = IPC_GET_ARG1(call);
682 arg2 = IPC_GET_ARG2(call);
683 screenbuffer_set_rgb_color(&cons->scr, arg1, arg2);
684 if (cons == active_console)
685 set_rgb_color(arg1, arg2);
686 break;
687 case CONSOLE_CURSOR_VISIBILITY:
688 fb_pending_flush();
689 arg1 = IPC_GET_ARG1(call);
690 cons->scr.is_cursor_visible = arg1;
691 if (cons == active_console)
692 curs_visibility(arg1);
693 break;
694 case CONSOLE_GET_EVENT:
695 async_serialize_end();
696 cons_get_event(cons, callid, &call);
697 async_serialize_start();
698 continue;
699 case CONSOLE_KCON_ENABLE:
700 change_console(kernel_console);
701 break;
702 }
703 ipc_answer_3(callid, EOK, arg1, arg2, arg3);
704 }
705}
706
707static void interrupt_received(ipc_callid_t callid, ipc_call_t *call)
708{
709 change_console(prev_console);
710}
711
712static bool console_init(void)
713{
714 /* Connect to keyboard driver */
715
716 kbd_phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_KEYBOARD, 0, 0);
717 if (kbd_phone < 0) {
718 printf(NAME ": Failed to connect to keyboard service\n");
719 return false;
720 }
721
722 ipcarg_t phonehash;
723 if (ipc_connect_to_me(kbd_phone, SERVICE_CONSOLE, 0, 0, &phonehash) != 0) {
724 printf(NAME ": Failed to create callback from keyboard service\n");
725 return false;
726 }
727
728 async_set_pending(process_pending_input);
729 async_new_connection(phonehash, 0, NULL, keyboard_events);
730
731 /* Connect to framebuffer driver */
732 fb_info.phone = ipc_connect_me_to_blocking(PHONE_NS, SERVICE_VIDEO, 0, 0);
733 if (fb_info.phone < 0) {
734 printf(NAME ": Failed to connect to video service\n");
735 return -1;
736 }
737
738 /* Register driver */
739 int rc = devmap_driver_register(NAME, client_connection);
740 if (rc < 0) {
741 printf(NAME ": Unable to register driver (%d)\n", rc);
742 return false;
743 }
744
745 /* Initialize gcons */
746 gcons_init(fb_info.phone);
747
748 /* Synchronize, the gcons could put something in queue */
749 async_req_0_0(fb_info.phone, FB_FLUSH);
750 async_req_0_2(fb_info.phone, FB_GET_CSIZE, &fb_info.cols, &fb_info.rows);
751
752 /* Set up shared memory buffer. */
753 size_t ib_size = sizeof(keyfield_t) * fb_info.cols * fb_info.rows;
754 interbuffer = as_get_mappable_page(ib_size);
755
756 if (as_area_create(interbuffer, ib_size, AS_AREA_READ |
757 AS_AREA_WRITE | AS_AREA_CACHEABLE) != interbuffer)
758 interbuffer = NULL;
759
760 if (interbuffer) {
761 if (ipc_share_out_start(fb_info.phone, interbuffer,
762 AS_AREA_READ) != EOK) {
763 as_area_destroy(interbuffer);
764 interbuffer = NULL;
765 }
766 }
767
768 fb_pending.cnt = 0;
769
770 /* Inititalize consoles */
771 size_t i;
772 for (i = 0; i < CONSOLE_COUNT; i++) {
773 if (i != KERNEL_CONSOLE) {
774 if (screenbuffer_init(&consoles[i].scr,
775 fb_info.cols, fb_info.rows) == NULL) {
776 printf(NAME ": Unable to allocate screen buffer %u\n", i);
777 return false;
778 }
779 screenbuffer_clear(&consoles[i].scr);
780 keybuffer_init(&consoles[i].keybuffer);
781 consoles[i].index = i;
782 consoles[i].refcount = 0;
783
784 char vc[MAX_DEVICE_NAME];
785 snprintf(vc, MAX_DEVICE_NAME, "vc%u", i);
786
787 if (devmap_device_register(vc, &consoles[i].dev_handle) != EOK) {
788 devmap_hangup_phone(DEVMAP_DRIVER);
789 printf(NAME ": Unable to register device %s\n", vc);
790 return false;
791 }
792 }
793 }
794
795 /* Initialize the screen */
796 set_rgb_color(DEFAULT_FOREGROUND, DEFAULT_BACKGROUND);
797 screen_clear();
798 curs_goto(0, 0);
799 curs_visibility(active_console->scr.is_cursor_visible);
800
801 /* Receive kernel notifications */
802 if (event_subscribe(EVENT_KCONSOLE, 0) != EOK)
803 printf(NAME ": Error registering kconsole notifications\n");
804
805 async_set_interrupt_received(interrupt_received);
806
807 return true;
808}
809
810int main(int argc, char *argv[])
811{
812 printf(NAME ": HelenOS Console service\n");
813
814 /* Disable kernel output to the console */
815 __SYSCALL0(SYS_DEBUG_DISABLE_CONSOLE);
816
817 if (!console_init()) {
818 __SYSCALL0(SYS_DEBUG_ENABLE_CONSOLE);
819 return -1;
820 }
821
822 printf(NAME ": Accepting connections\n");
823 async_manager();
824
825 return 0;
826}
827
828/** @}
829 */
Note: See TracBrowser for help on using the repository browser.