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