blob: 35375394af3dd59c3763f61e5d2e13553060b55d [file] [log] [blame]
Corey Tabaka84697242009-03-26 02:32:01 -04001/*
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>
Corey Tabakab3f6cac2009-04-01 17:35:12 -040024#include <platform/pc.h>
Corey Tabaka84697242009-03-26 02:32:01 -040025#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 view_window.x1 = x1;
146 view_window.y1 = y1;
147 view_window.x2 = x2;
148 view_window.y2 = y2;
149
150 //place(x1, y1);
151}
152
153void _clear(char c,char attr,int x1,int y1,int x2,int y2)
154{
155 register int i,j;
156 unsigned short w = attr;
157
158 w <<= 8; w |= c;
159 for (i = x1; i <= x2; i++) {
160 for (j = y1; j <= y2; j++) {
161 *((unsigned short *)(0xB8000 + 2*i+160*j + 2*active_page*VPAGE_SIZE)) = w;
162 }
163 }
164
165 place(x1,y1);
166 curr_y = y1;
167 curr_x = x1;
168}
169
170void clear()
171{
172 _clear(' ', curr_attr, view_window.x1, view_window.y1, view_window.x2,
173 view_window.y2);
174}
175
176void _scroll(char attr, int x1, int y1, int x2, int y2)
177{
178 register int x,y;
179 unsigned short xattr = attr << 8,w;
180 unsigned char *v = (unsigned char *)(0xB8000 + active_page*(2*VPAGE_SIZE));
181
182 for (y = y1+1; y <= y2; y++) {
183 for (x = x1; x <= x2; x++) {
184 w = *((unsigned short *) (v + 2*(y*80+x)));
185 *((unsigned short *)(v + 2*((y-1)*80+x))) = w;
186 }
187 }
188
189 for (x = x1; x <= x2; x++) {
190 *((unsigned short *)(v + 2*((y-1)*80+x))) = xattr;
191 }
192}
193
194void scroll(void)
195{
196 _scroll(curr_attr, view_window.x1, view_window.y1, view_window.x2,
197 view_window.y2);
198}
199
200void cputc(char c)
201{
202 static unsigned short scan_x, x, y;
203 unsigned char *v = (unsigned char *)(0xB8000 + active_page*(2*VPAGE_SIZE));
204 x = curr_x;
205 y = curr_y;
206
207 switch (c) {
208 case '\t':
209 x += 8;
210 if (x >= view_window.x2+1) {
211 x = view_window.x1;
212 if (y == view_window.y2) {
213 scroll();
214 } else {
215 y++;
216 }
217 } else {
218 scan_x = 0;
219
220 while ((scan_x+8) < x) {
221 scan_x += 8;
222 }
223
224 x = scan_x;
225 }
226 break;
227
228 case '\n':
229 x = view_window.x1;
230 if (y == view_window.y2) {
231 scroll();
232 } else {
233 y++;
234 }
235 break;
236
237 case '\b':
238 x--;
239 *(v + 2*(x + y*80)) = ' ';
240 break;
241
242 default:
243 *(v + 2*(x + y*80)) = c;
244 x++;
245
246 if (x >= view_window.x2+1) {
247 x = view_window.x1;
248 if (y == view_window.y2) {
249 scroll();
250 } else {
251 y++;
252 }
253 }
254 }
255
256 place(x, y);
257}
258
259void cputs(char *s)
260{
261 char c;
262 while (*s != '\0') {
263 c = *s++;
264 cputc(c);
265 }
266}
267
268void puts_xy(int x,int y,char attr,char *s)
269{
270 unsigned char *v = (unsigned char *)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
271 while (*s != 0) {
272 *v = *s; s++; v++;
273 *v = attr; v++;
274 }
275}
276
277void putc_xy(int x, int y, char attr, char c)
278{
279 unsigned char *v = (unsigned char *)(0xB8000 + (80*y+x)*2 + active_page*(2*VPAGE_SIZE));
280 *v = c; v++;
281 *v = attr;
282}
283
284int printf_xy(int x, int y, char attr, char *fmt, ...)
285{
286 char cbuf[200];
287 va_list parms;
288 int result;
289
290 va_start(parms, fmt);
291 result = vsprintf(cbuf, fmt, parms);
292 va_end(parms);
293
294 puts_xy(x, y, attr, cbuf);
295
296 return result;
297}