blob: d4ccabdcbd55a69fbfbdf9fac07a12aa9fcd2162 [file] [log] [blame]
rjw1f884582022-01-06 17:20:42 +08001/*
2 * Copyright (c) 2009 Corey Tabaka
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining
5 * a copy of this software and associated documentation files
6 * (the "Software"), to deal in the Software without restriction,
7 * including without limitation the rights to use, copy, modify, merge,
8 * publish, distribute, sublicense, and/or sell copies of the Software,
9 * and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
18 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
19 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
20 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
21 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22 */
23#include <arch/x86.h>
24#include <platform/pc.h>
25#include <platform/console.h>
26#include <string.h>
27#include <stdlib.h>
28#include <stdio.h>
29#include <stdarg.h>
30
31/* CGA values */
32#define CURSOR_START 0x0A
33#define CURSOR_END 0x0B
34#define VIDEO_ADDRESS_MSB 0x0C
35#define VIDEO_ADDRESS_LSB 0x0D
36#define CURSOR_POS_MSB 0x0E
37#define CURSOR_POS_LSB 0x0F
38
39/* curr settings */
40static unsigned char curr_x;
41static unsigned char curr_y;
42static unsigned char curr_start;
43static unsigned char curr_end;
44static unsigned char curr_attr;
45
46/* video page buffer */
47#define VPAGE_SIZE 2048
48#define PAGE_MAX 8
49
50static int active_page = 0;
51static int visual_page = 0;
52
53static int curs_x[PAGE_MAX];
54static int curs_y[PAGE_MAX];
55
56static struct {
57 int x1, y1, x2, y2;
58} view_window = {
59 0, 0, 79, 24
60};
61
62void platform_init_console(void)
63{
64 curr_save();
65 window(0, 0, 79, 24);
66 clear();
67 place(0, 0);
68}
69
70void set_visual_page(int page)
71{
72 unsigned short page_offset = page*VPAGE_SIZE;
73 visual_page = page;
74
75 outp(CGA_INDEX_REG, VIDEO_ADDRESS_LSB);
76 outp(CGA_DATA_REG, page_offset & 0xFF);
77 outp(CGA_INDEX_REG, VIDEO_ADDRESS_MSB);
78 outp(CGA_DATA_REG, (page_offset >> 8) & 0xFF);
79}
80
81void set_active_page(int page)
82{
83 curs_x[active_page] = curr_x;
84 curs_y[active_page] = curr_y;
85 curr_x = curs_x[page];
86 curr_y = curs_y[page];
87 active_page = page;
88}
89
90int get_visual_page(void)
91{
92 return visual_page;
93}
94
95int get_active_page(void)
96{
97 return active_page;
98}
99
100void place(int x,int y)
101{
102 unsigned short cursor_word = x + y*80 + active_page*VPAGE_SIZE;
103
104 /*
105 * program CGA using index reg, then data reg
106 */
107 outp(CGA_INDEX_REG, CURSOR_POS_LSB);
108 outp(CGA_DATA_REG, cursor_word & 0xFF);
109 outp(CGA_INDEX_REG, CURSOR_POS_MSB);
110 outp(CGA_DATA_REG, (cursor_word >> 8) & 0xFF);
111
112 curr_x = x;
113 curr_y = y;
114}
115
116void cursor(int start,int end)
117{
118 outp(CGA_INDEX_REG, CURSOR_START);
119 outp(CGA_DATA_REG, start);
120 outp(CGA_INDEX_REG, CURSOR_END);
121 outp(CGA_DATA_REG, end);
122}
123
124void curr_save(void)
125{
126 /* grab some info from the bios data area (these should be defined in memmap.h */
127 curr_attr = *((unsigned char *)0xB8000 + 159);
128 curr_x = *((unsigned char *)0x00450);
129 curr_y = *((unsigned char *)0x00451);
130 curr_end = *((unsigned char *)0x00460);
131 curr_start = *((unsigned char *)0x00461);
132 active_page = visual_page = 0;
133}
134
135void curr_restore(void)
136{
137 *((unsigned char *)0x00450) = curr_x;
138 *((unsigned char *)0x00451) = curr_y;
139
140 place(curr_x, curr_y);
141 cursor(curr_start, curr_end);
142}
143
144void window(int x1, int y1, int x2, int y2)
145{
146 view_window.x1 = x1;
147 view_window.y1 = y1;
148 view_window.x2 = x2;
149 view_window.y2 = y2;
150
151 //place(x1, y1);
152}
153
154void _clear(char c,char attr,int x1,int y1,int x2,int y2)
155{
156 register int i,j;
157 unsigned short w = attr;
158
159 w <<= 8;
160 w |= c;
161 for (i = x1; i <= x2; i++) {
162 for (j = y1; j <= y2; j++) {
163 *((unsigned short *)(uintptr_t)(0xB8000 + 2*i+160*j + 2 * active_page * VPAGE_SIZE)) = w;
164 }
165 }
166
167 place(x1,y1);
168 curr_y = y1;
169 curr_x = x1;
170}
171
172void clear()
173{
174 _clear(' ', curr_attr, view_window.x1, view_window.y1, view_window.x2,
175 view_window.y2);
176}
177
178void _scroll(char attr, int x1, int y1, int x2, int y2)
179{
180 register int x,y;
181 unsigned short xattr = attr << 8,w;
182 unsigned char *v = (unsigned char *)(uintptr_t)(0xB8000 + active_page*(2*VPAGE_SIZE));
183
184 for (y = y1+1; y <= y2; y++) {
185 for (x = x1; x <= x2; x++) {
186 w = *((unsigned short *) (v + 2*(y*80+x)));
187 *((unsigned short *)(v + 2*((y-1)*80+x))) = w;
188 }
189 }
190
191 for (x = x1; x <= x2; x++) {
192 *((unsigned short *)(v + 2*((y-1)*80+x))) = xattr;
193 }
194}
195
196void scroll(void)
197{
198 _scroll(curr_attr, view_window.x1, view_window.y1, view_window.x2,
199 view_window.y2);
200}
201
202void cputc(char c)
203{
204 static unsigned short scan_x, x, y;
205 unsigned char *v = (unsigned char *)(uintptr_t)(0xB8000 + active_page*(2*VPAGE_SIZE));
206 x = curr_x;
207 y = curr_y;
208
209 switch (c) {
210 case '\t':
211 x += 8;
212 if (x >= view_window.x2+1) {
213 x = view_window.x1;
214 if (y == view_window.y2) {
215 scroll();
216 } else {
217 y++;
218 }
219 } else {
220 scan_x = 0;
221
222 while ((scan_x+8) < x) {
223 scan_x += 8;
224 }
225
226 x = scan_x;
227 }
228 break;
229
230 case '\r':
231 x = view_window.x1;
232 break;
233
234 case '\n':
235 if (y == view_window.y2) {
236 scroll();
237 } else {
238 y++;
239 }
240 break;
241
242 case '\b':
243 x--;
244 *(v + 2*(x + y*80)) = ' ';
245 break;
246
247 default:
248 *(v + 2*(x + y*80)) = c;
249 x++;
250
251 if (x >= view_window.x2+1) {
252 x = view_window.x1;
253 if (y == view_window.y2) {
254 scroll();
255 } else {
256 y++;
257 }
258 }
259 }
260
261 place(x, y);
262}
263
264void cputs(char *s)
265{
266 char c;
267 while (*s != '\0') {
268 c = *s++;
269 cputc(c);
270 }
271}
272
273void puts_xy(int x,int y,char attr,char *s)
274{
275 unsigned char *v = (unsigned char *)(uintptr_t)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
276 while (*s != 0) {
277 *v = *s;
278 s++;
279 v++;
280 *v = attr;
281 v++;
282 }
283}
284
285void putc_xy(int x, int y, char attr, char c)
286{
287 unsigned char *v = (unsigned char *)(uintptr_t)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
288 *v = c;
289 v++;
290 *v = attr;
291}
292
293int printf_xy(int x, int y, char attr, char *fmt, ...)
294{
295 char cbuf[200];
296 va_list parms;
297 int result;
298
299 va_start(parms, fmt);
300 result = vsprintf(cbuf, fmt, parms);
301 va_end(parms);
302
303 puts_xy(x, y, attr, cbuf);
304
305 return result;
306}