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