1/**
2 * \file
3 */
4
5/*
6 * Copyright (c) 2009, ETH Zurich.
7 * All rights reserved.
8 *
9 * This file is distributed under the terms in the attached LICENSE file.
10 * If you do not find this file, copies can be found by writing to:
11 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group.
12 */
13
14#include "vmkitmon.h"
15#include "console.h"
16#include <stdlib.h>
17#include <stdio.h>
18#include <barrelfish/terminal.h>
19
20struct console *
21console_new (void)
22{
23    struct console *ret = calloc(1, sizeof(struct console));
24    return ret;
25}
26
27static int
28handle_set_cursor_position (struct console *c, struct guest *g)
29{
30    // only support mode 0 for now
31    if (guest_get_bh(g) != 0) {
32        return HANDLER_ERR_UNHANDELED;
33    }
34
35    c->cursor_pos_x = guest_get_dl(g);
36    c->cursor_pos_y = guest_get_dh(g);
37
38    return HANDLER_ERR_OK;
39}
40
41static int
42handle_write_char_with_attr (struct console *c, struct guest *g)
43{
44    // only support mode 0 for now
45    if (guest_get_bh(g) != 0) {
46        return HANDLER_ERR_UNHANDELED;
47    }
48    // we only support "normal" text output atm
49    if (guest_get_bl(g) != 7) {
50        return HANDLER_ERR_UNHANDELED;
51    }
52
53    // FIXME: Here we completely ignore the postition of the cursor atm since we
54    //        do not have proper terminal support in BF.
55    //        We also ignore multiple char writes, they make no sense atm.
56    int r;
57    char chr = guest_get_al(g);
58
59    r = terminal_write(&chr, 1);
60    assert(r == 1);
61
62    return HANDLER_ERR_OK;
63}
64
65static int
66handle_teletype_output (struct console *c, struct guest *g)
67{
68    // only support mode 0 for now
69    if (guest_get_bh(g) != 0) {
70        return HANDLER_ERR_UNHANDELED;
71    }
72
73    // we do not yet have a real understanding of the terminal, assume it is
74    // 80x25 and we simply insert new lines at the end of the "screen"
75    int r;
76    char chr = guest_get_al(g);
77
78    // treat CR and LF as column clearing chars
79    if (chr == '\r' || chr == '\n') {
80        c->cursor_pos_x = 0;
81    }
82    // insert a CR if we are passed the last column of the screen
83    else if (c->cursor_pos_x > 79) {
84        r = terminal_write("\n", 1);
85        assert(r == 1);
86        c->cursor_pos_x = 0;
87    }
88    // in all other cases just increase the column
89    else {
90        c->cursor_pos_x++;
91    }
92
93    r = terminal_write(&chr, 1);
94    assert(r == 1);
95
96    return HANDLER_ERR_OK;
97}
98
99static int
100handle_get_cursor_pos_and_size (struct console *c, struct guest *g)
101{
102    // only support mode 0 for now
103    if (guest_get_bh(g) != 0) {
104        return HANDLER_ERR_UNHANDELED;
105    }
106
107    // set ax to 0
108    guest_set_ax(g, 0);
109    // we do not support scan-lines
110    guest_set_cx(g, 0);
111
112    // set the position
113    guest_set_dl(g, c->cursor_pos_x);
114    guest_set_dh(g, c->cursor_pos_y);
115
116    return HANDLER_ERR_OK;
117}
118
119static int
120handle_set_text_cursor_shape (struct console *c, struct guest *g)
121{
122    // we only handle primitive cursors
123    if (guest_get_cx(g) != 0) {
124        printf("console: Unsupported cursor requested\n");
125        return HANDLER_ERR_FATAL;
126    }
127
128    return HANDLER_ERR_OK;
129}
130
131static int
132handle_get_current_video_mode (struct console *c, struct guest *g)
133{
134    // FIXME: for the terminal to be more flexible this should not be hardcoded
135    guest_set_ah(g, 80),
136    guest_set_al(g, 0x6); // VGA, 80x25, 8x8 box, res 640x200, 2 colors
137    guest_set_bh(g, 0);
138
139    return HANDLER_ERR_OK;
140}
141
142static int
143handle_get_ega_info (struct console *c, struct guest *g)
144{
145    // FIXME: only partially implemented, linux wants BX to be 0x10 to believe
146    //        it is confronted with a CGA card.
147    guest_set_bx(g, 0x10);
148
149    return HANDLER_ERR_OK;
150}
151
152static int
153handle_get_svga_info (struct console *c, struct guest *g)
154{
155    // we do not support vesa yet
156    guest_set_ax(g, 0);
157
158    return HANDLER_ERR_OK;
159}
160
161static int
162handle_set_video_mode (struct console *c, struct guest *g)
163{
164    // FIXME: Ignored for now.
165
166    return HANDLER_ERR_OK;
167}
168
169int
170console_handle_int10 (struct console *c, struct guest *g)
171{
172    // VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION
173    if (guest_get_ax(g) == 0x4f00) {
174        return handle_get_svga_info(c, g);
175    }
176    // VIDEO - SET VIDEO MODE
177    if (guest_get_ah(g) == 0x0) {
178        return handle_set_video_mode(c, g);
179    }
180    // VIDEO - SET TEXT-MODE CURSOR SHAPE
181    if (guest_get_ah(g) == 0x1) {
182        return handle_set_text_cursor_shape(c, g);
183    }
184    // VIDEO - SET CURSOR POSITION
185    else if (guest_get_ah(g) == 0x2) {
186        return handle_set_cursor_position(c, g);
187    }
188    // VIDEO - GET CURSOR POSITION AND SIZE
189    else if (guest_get_ah(g) == 0x3) {
190        return handle_get_cursor_pos_and_size(c, g);
191    }
192    // VIDEO - WRITE CHARACTER AND ATTRIBUTE AT CURSOR POSITION
193    else if (guest_get_ah(g) == 0x9) {
194        return handle_write_char_with_attr(c, g);
195    }
196    // VIDEO - TELETYPE OUTPUT
197    else if (guest_get_ah(g) == 0xe) {
198        return handle_teletype_output(c, g);
199    }
200    // VIDEO - GET CURRENT VIDEO MODEL_CGA
201    else if (guest_get_ah(g) == 0xf) {
202        return handle_get_current_video_mode(c, g);
203    }
204    // VIDEO - ALTERNATE FUNCTION SELECT (PS, EGA, VGA, MCGA) - GET EGA INFO
205    else if (guest_get_ah(g) == 0x12 && guest_get_bl(g) == 0x10) {
206        return handle_get_ega_info(c, g);
207    }
208
209    return HANDLER_ERR_UNHANDELED;
210}
211