xref: /haiku/src/system/boot/platform/bios_ia32/console.cpp (revision b30304acc8c37e678a1bf66976d15bdab103f931)
1 /*
2  * Copyright 2004-2005, Axel Dörfler, axeld@pinc-software.de. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  */
5 
6 
7 #include "console.h"
8 #include "keyboard.h"
9 
10 #include <SupportDefs.h>
11 #include <util/kernel_cpp.h>
12 #include <boot/stage2.h>
13 
14 #include <string.h>
15 
16 
17 class Console : public ConsoleNode {
18 	public:
19 		Console();
20 
21 		virtual ssize_t ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize);
22 		virtual ssize_t WriteAt(void *cookie, off_t pos, const void *buffer, size_t bufferSize);
23 };
24 
25 static uint16 *sScreenBase = (uint16 *)0xb8000;
26 static uint32 sScreenWidth = 80;
27 static uint32 sScreenHeight = 25;
28 static uint32 sScreenOffset = 0;
29 static uint16 sColor = 0x0f00;
30 
31 static Console sInput, sOutput;
32 FILE *stdin, *stdout, *stderr;
33 
34 
35 static void
36 scroll_up()
37 {
38 	memcpy(sScreenBase, sScreenBase + sScreenWidth,
39 		sScreenWidth * sScreenHeight * 2 - sScreenWidth * 2);
40 	sScreenOffset = (sScreenHeight - 1) * sScreenWidth;
41 
42 	for (uint32 i = 0; i < sScreenWidth; i++)
43 		sScreenBase[sScreenOffset + i] = sColor | ' ';
44 }
45 
46 
47 //	#pragma mark -
48 
49 
50 Console::Console()
51 	: ConsoleNode()
52 {
53 }
54 
55 
56 ssize_t
57 Console::ReadAt(void *cookie, off_t pos, void *buffer, size_t bufferSize)
58 {
59 	// don't seek in character devices
60 	// not implemented (and not yet? needed)
61 	return B_ERROR;
62 }
63 
64 
65 ssize_t
66 Console::WriteAt(void *cookie, off_t /*pos*/, const void *buffer, size_t bufferSize)
67 {
68 	const char *string = (const char *)buffer;
69 
70 	if (gKernelArgs.frame_buffer.enabled)
71 		return bufferSize;
72 
73 	for (uint32 i = 0; i < bufferSize; i++) {
74 		if (string[0] == '\n')
75 			sScreenOffset += sScreenWidth - (sScreenOffset % sScreenWidth);
76 		else
77 			sScreenBase[sScreenOffset++] = sColor | string[0];
78 
79 		if (sScreenOffset >= sScreenWidth * sScreenHeight)
80 			scroll_up();
81 
82 		string++;
83 	}
84 	return bufferSize;
85 }
86 
87 
88 //	#pragma mark -
89 
90 
91 void
92 console_clear_screen(void)
93 {
94 	if (gKernelArgs.frame_buffer.enabled)
95 		return;
96 
97 	for (uint32 i = 0; i < sScreenWidth * sScreenHeight; i++)
98 		sScreenBase[i] = sColor;
99 
100 	// reset cursor position as well
101 	sScreenOffset = 0;
102 }
103 
104 
105 int32
106 console_width(void)
107 {
108 	return sScreenWidth;
109 }
110 
111 
112 int32
113 console_height(void)
114 {
115 	return sScreenHeight;
116 }
117 
118 
119 void
120 console_set_cursor(int32 x, int32 y)
121 {
122 	if (y >= (int32)sScreenHeight)
123 		y = sScreenHeight - 1;
124 	else if (y < 0)
125 		y = 0;
126 	if (x >= (int32)sScreenWidth)
127 		x = sScreenWidth - 1;
128 	else if (x < 0)
129 		x = 0;
130 
131 	sScreenOffset = x + y * sScreenWidth;
132 }
133 
134 
135 void
136 console_set_color(int32 foreground, int32 background)
137 {
138 	sColor = (background & 0xf) << 12 | (foreground & 0xf) << 8;
139 }
140 
141 
142 int
143 console_wait_for_key(void)
144 {
145 	union key key = wait_for_key();
146 
147 	if (key.code.ascii == 0) {
148 		switch (key.code.bios) {
149 			case BIOS_KEY_UP:
150 				return TEXT_CONSOLE_KEY_UP;
151 			case BIOS_KEY_DOWN:
152 				return TEXT_CONSOLE_KEY_DOWN;
153 			case BIOS_KEY_PAGE_UP:
154 				return TEXT_CONSOLE_KEY_PAGE_UP;
155 			case BIOS_KEY_PAGE_DOWN:
156 				return TEXT_CONSOLE_KEY_PAGE_DOWN;
157 			case BIOS_KEY_HOME:
158 				return TEXT_CONSOLE_KEY_HOME;
159 			case BIOS_KEY_END:
160 				return TEXT_CONSOLE_KEY_END;
161 			default:
162 				return 0;
163 		}
164 	} else
165 		return key.code.ascii;
166 }
167 
168 
169 status_t
170 console_init(void)
171 {
172 	// ToDo: make screen size changeable via stage2_args
173 
174 	console_clear_screen();
175 
176 	// enable stdio functionality
177 	stdin = (FILE *)&sInput;
178 	stdout = stderr = (FILE *)&sOutput;
179 
180 	return B_OK;
181 }
182 
183