xref: /haiku/src/system/boot/platform/bios_ia32/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 "keyboard.h"
10 #include "video.h"
11 
12 #include <SupportDefs.h>
13 #include <util/kernel_cpp.h>
14 #include <boot/stage2.h>
15 
16 #include <string.h>
17 
18 
19 class Console : public ConsoleNode {
20 	public:
21 		Console();
22 
23 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize);
24 		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);
25 
26 		virtual void	ClearScreen();
27 		virtual int32	Width();
28 		virtual int32	Height();
29 		virtual void	SetCursor(int32 x, int32 y);
30 		virtual void	SetCursorVisible(bool visible);
31 		virtual void	SetColors(int32 foreground, int32 background);
32 };
33 
34 static uint16 *sScreenBase = (uint16 *)0xb8000;
35 static uint32 sScreenWidth = 80;
36 static uint32 sScreenHeight = 25;
37 static uint32 sScreenOffset = 0;
38 static uint16 sColor = 0x0f00;
39 
40 extern ConsoleNode* gConsoleNode;
41 static Console sConsole;
42 FILE *stdin, *stdout, *stderr;
43 
44 
45 static void
46 scroll_up()
47 {
48 	memcpy(sScreenBase, sScreenBase + sScreenWidth,
49 		sScreenWidth * sScreenHeight * 2 - sScreenWidth * 2);
50 	sScreenOffset = (sScreenHeight - 1) * sScreenWidth;
51 
52 	for (uint32 i = 0; i < sScreenWidth; i++)
53 		sScreenBase[sScreenOffset + i] = sColor | ' ';
54 }
55 
56 
57 //	#pragma mark -
58 
59 
60 Console::Console()
61 	: ConsoleNode()
62 {
63 }
64 
65 
66 ssize_t
67 Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
68 {
69 	// don't seek in character devices
70 	// not implemented (and not yet? needed)
71 	return B_ERROR;
72 }
73 
74 
75 ssize_t
76 Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferSize)
77 {
78 	const char *string = (const char *)buffer;
79 
80 	if (gKernelArgs.frame_buffer.enabled)
81 		return bufferSize;
82 
83 	for (uint32 i = 0; i < bufferSize; i++) {
84 		if (string[0] == '\n')
85 			sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth);
86 		else
87 			sScreenBase[sScreenOffset++] = sColor | string[0];
88 
89 		if (sScreenOffset >= sScreenWidth * sScreenHeight)
90 			scroll_up();
91 
92 		string++;
93 	}
94 	return bufferSize;
95 }
96 
97 
98 void
99 Console::ClearScreen()
100 {
101 	if (gKernelArgs.frame_buffer.enabled)
102 		return;
103 
104 	for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++)
105 		sScreenBase[i] = sColor;
106 
107 	// reset cursor position as well
108 	sScreenOffset = 0;
109 }
110 
111 
112 int32
113 Console::Width()
114 {
115 	return sScreenWidth;
116 }
117 
118 
119 int32
120 Console::Height()
121 {
122 	return sScreenHeight;
123 }
124 
125 
126 void
127 Console::SetCursor(int32 x, int32 y)
128 {
129 	if (y >= (int32)sScreenHeight)
130 		y = sScreenHeight - 1;
131 	else if (y < 0)
132 		y = 0;
133 	if (x >= (int32)sScreenWidth)
134 		x = sScreenWidth - 1;
135 	else if (x < 0)
136 		x = 0;
137 
138 	sScreenOffset = x + y * sScreenWidth;
139 	video_move_text_cursor(x, y);
140 }
141 
142 
143 void
144 Console::SetCursorVisible(bool visible)
145 {
146 	if (visible)
147 		video_show_text_cursor();
148 	else
149 		video_hide_text_cursor();
150 }
151 
152 
153 void
154 Console::SetColors(int32 foreground, int32 background)
155 {
156 	sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8;
157 }
158 
159 
160 int
161 console_wait_for_key(void)
162 {
163 	union key key = wait_for_key();
164 
165 	if (key.code.ascii == 0) {
166 		switch (key.code.bios) {
167 			case BIOS_KEY_UP:
168 				return TEXT_CONSOLE_KEY_UP;
169 			case BIOS_KEY_DOWN:
170 				return TEXT_CONSOLE_KEY_DOWN;
171 			case BIOS_KEY_LEFT:
172 				return TEXT_CONSOLE_KEY_LEFT;
173 			case BIOS_KEY_RIGHT:
174 				return TEXT_CONSOLE_KEY_RIGHT;
175 			case BIOS_KEY_PAGE_UP:
176 				return TEXT_CONSOLE_KEY_PAGE_UP;
177 			case BIOS_KEY_PAGE_DOWN:
178 				return TEXT_CONSOLE_KEY_PAGE_DOWN;
179 			case BIOS_KEY_HOME:
180 				return TEXT_CONSOLE_KEY_HOME;
181 			case BIOS_KEY_END:
182 				return TEXT_CONSOLE_KEY_END;
183 			default:
184 				return 0;
185 		}
186 	} else
187 		return key.code.ascii;
188 }
189 
190 
191 status_t
192 console_init(void)
193 {
194 	// ToDo: make screen size changeable via stage2_args
195 
196 	gConsoleNode = &sConsole;
197 
198 	console_clear_screen();
199 
200 	// enable stdio functionality
201 	stdin = (FILE *)&sConsole;
202 	stdout = stderr = (FILE *)&sConsole;
203 
204 	return B_OK;
205 }
206 
207