xref: /haiku/src/system/boot/platform/riscv/console.cpp (revision a5061ecec55353a5f394759473f1fd6df04890da)
1 /*
2  * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Copyright 2011, Rene Gollent, rene@gollent.com. All rights reserved.
4  * Distributed under the terms of the MIT License.
5  */
6 
7 
8 #include "console.h"
9 #include "video.h"
10 #include "graphics.h"
11 #include <Htif.h>
12 #include "virtio.h"
13 
14 #include <SupportDefs.h>
15 #include <util/kernel_cpp.h>
16 #include <boot/stage2.h>
17 
18 #include <string.h>
19 
20 
21 class Console : public ConsoleNode {
22 	public:
23 		Console();
24 
25 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer,
26 			size_t bufferSize);
27 		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer,
28 			size_t bufferSize);
29 };
30 
31 static uint16* sScreenBase;
32 static uint32 sScreenOfsX = 0;
33 static uint32 sScreenOfsY = 0;
34 static uint32 sScreenWidth = 80;
35 static uint32 sScreenHeight = 25;
36 static uint32 sScreenOffset = 0;
37 static uint16 sColor = 0x0f00;
38 
39 static Console sInput, sOutput;
40 FILE *stdin, *stdout, *stderr;
41 
42 
43 static const uint32 kPalette[] = {
44 	0x000000,
45 	0x0000aa,
46 	0x00aa00,
47 	0x00aaaa,
48 	0xaa0000,
49 	0xaa00aa,
50 	0xaa5500,
51 	0xaaaaaa,
52 	0x555555,
53 	0x5555ff,
54 	0x55ff55,
55 	0x55ffff,
56 	0xff5555,
57 	0xff55ff,
58 	0xffff55,
59 	0xffffff
60 };
61 
62 
63 static void
64 RefreshFramebuf(int32 x0, int32 y0, int32 w, int32 h)
65 {
66 	for (int32 y = y0; y < y0 + h; y++)
67 		for (int32 x = x0; x < x0 + w; x++) {
68 			uint16 cell = sScreenBase[x + y * sScreenWidth];
69 			int32 charX = sScreenOfsX + x*gFixedFont.charWidth;
70 			int32 charY = sScreenOfsY + y*gFixedFont.charHeight;
71 			uint32 bgColor = kPalette[cell / 0x1000 % 0x10];
72 			uint32 fontColor = kPalette[cell / 0x100 % 0x10];
73 			Clear(gFramebuf.Clip(charX, charY, gFixedFont.charWidth,
74 				gFixedFont.charHeight), bgColor);
75 			BlitMaskRgb(gFramebuf, gFixedFont.ThisGlyph(cell % 0x100),
76 				charX, charY, fontColor);
77 		}
78 }
79 
80 
81 static void
82 scroll_up()
83 {
84 	memcpy(sScreenBase, sScreenBase + sScreenWidth,
85 		sScreenWidth * sScreenHeight * 2 - sScreenWidth * 2);
86 	sScreenOffset = (sScreenHeight - 1) * sScreenWidth;
87 
88 	for (uint32 i = 0; i < sScreenWidth; i++)
89 		sScreenBase[sScreenOffset + i] = sColor | ' ';
90 }
91 
92 
93 //	#pragma mark -
94 
95 
96 Console::Console()
97 	: ConsoleNode()
98 {
99 }
100 
101 
102 ssize_t
103 Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
104 {
105 	// don't seek in character devices
106 	// not implemented (and not yet? needed)
107 	return B_ERROR;
108 }
109 
110 
111 ssize_t
112 Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer,
113 		size_t bufferSize)
114 {
115 	const char *string = (const char *)buffer;
116 
117 	if (gKernelArgs.frame_buffer.enabled)
118 		return bufferSize;
119 
120 	for (uint32 i = 0; i < bufferSize; i++) {
121 		if (string[0] == '\n') {
122 			sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth);
123 		} else {
124 			sScreenBase[sScreenOffset++] = sColor | string[0];
125 			RefreshFramebuf((sScreenOffset - 1) % sScreenWidth,
126 				(sScreenOffset - 1) / sScreenWidth, 1, 1);
127 		}
128 
129 		if (sScreenOffset >= sScreenWidth * sScreenHeight) {
130 			scroll_up();
131 			RefreshFramebuf(0, 0, sScreenWidth, sScreenHeight);
132 		}
133 
134 		string++;
135 	}
136 
137 	return bufferSize;
138 }
139 
140 
141 //	#pragma mark -
142 
143 
144 void
145 console_clear_screen(void)
146 {
147 	if (gKernelArgs.frame_buffer.enabled)
148 		return;
149 
150 	for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++)
151 		sScreenBase[i] = sColor;
152 
153 	// reset cursor position as well
154 	sScreenOffset = 0;
155 
156 	RefreshFramebuf(0, 0, sScreenWidth, sScreenHeight);
157 }
158 
159 
160 int32
161 console_width(void)
162 {
163 	return sScreenWidth;
164 }
165 
166 
167 int32
168 console_height(void)
169 {
170 	return sScreenHeight;
171 }
172 
173 
174 void
175 console_set_cursor(int32 x, int32 y)
176 {
177 	if (y >= (int32)sScreenHeight)
178 		y = sScreenHeight - 1;
179 	else if (y < 0)
180 		y = 0;
181 	if (x >= (int32)sScreenWidth)
182 		x = sScreenWidth - 1;
183 	else if (x < 0)
184 		x = 0;
185 
186 	sScreenOffset = x + y * sScreenWidth;
187 }
188 
189 
190 void
191 console_show_cursor(void)
192 {
193 	// TODO: implement
194 }
195 
196 
197 void
198 console_hide_cursor(void)
199 {
200 	// TODO: implement
201 }
202 
203 
204 void
205 console_set_color(int32 foreground, int32 background)
206 {
207 	sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8;
208 }
209 
210 
211 int
212 console_wait_for_key(void)
213 {
214 	int key = virtio_input_wait_for_key();
215 
216 	switch (key) {
217 	case 71: return TEXT_CONSOLE_KEY_RETURN;
218 	case 30: return TEXT_CONSOLE_KEY_BACKSPACE;
219 	case  1: return TEXT_CONSOLE_KEY_ESCAPE;
220 	case 94: return TEXT_CONSOLE_KEY_SPACE;
221 
222 	case 87: return TEXT_CONSOLE_KEY_UP;
223 	case 98: return TEXT_CONSOLE_KEY_DOWN;
224 	case 97: return TEXT_CONSOLE_KEY_LEFT;
225 	case 99: return TEXT_CONSOLE_KEY_RIGHT;
226 	case 33: return TEXT_CONSOLE_KEY_PAGE_UP;
227 	case 54: return TEXT_CONSOLE_KEY_PAGE_DOWN;
228 	case 32: return TEXT_CONSOLE_KEY_HOME;
229 	case 53: return TEXT_CONSOLE_KEY_END;
230 
231 	default:
232 		return TEXT_CONSOLE_NO_KEY;
233 	}
234 }
235 
236 
237 status_t
238 console_init(void)
239 {
240 	sScreenWidth = 80;
241 	sScreenHeight = 25;
242 	sScreenOfsX = gFramebuf.width/2 - sScreenWidth*gFixedFont.charWidth/2;
243 	sScreenOfsY = gFramebuf.height/2 - sScreenHeight*gFixedFont.charHeight/2;
244 
245 	sScreenBase = new(std::nothrow) uint16[sScreenWidth * sScreenHeight];
246 
247 	console_clear_screen();
248 
249 	// enable stdio functionality
250 	stdin = (FILE *)&sInput;
251 	stdout = stderr = (FILE *)&sOutput;
252 
253 	return B_OK;
254 }
255