1 /*
2  * Copyright (C) 2003, 2004 Stefan Reinauer
3  *
4  * See the file "COPYING" for further information about
5  * the copyright and warranty status of this work.
6  */
7 
8 #include "config.h"
9 #include "kernel/kernel.h"
10 #include "openbios.h"
11 #include "libopenbios/console.h"
12 
13 #ifdef CONFIG_DEBUG_CONSOLE
14 
15 /* ******************************************************************
16  *                       serial console functions
17  * ****************************************************************** */
18 
19 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
20 
21 #define RBR(x)  x==2?0x2f8:0x3f8
22 #define THR(x)  x==2?0x2f8:0x3f8
23 #define IER(x)  x==2?0x2f9:0x3f9
24 #define IIR(x)  x==2?0x2fa:0x3fa
25 #define LCR(x)  x==2?0x2fb:0x3fb
26 #define MCR(x)  x==2?0x2fc:0x3fc
27 #define LSR(x)  x==2?0x2fd:0x3fd
28 #define MSR(x)  x==2?0x2fe:0x3fe
29 #define SCR(x)  x==2?0x2ff:0x3ff
30 #define DLL(x)  x==2?0x2f8:0x3f8
31 #define DLM(x)  x==2?0x2f9:0x3f9
32 
uart_charav(int port)33 static int uart_charav(int port)
34 {
35 	if (!port)
36 		return -1;
37 	return ((inb(LSR(port)) & 1) != 0);
38 }
39 
uart_getchar(int port)40 static char uart_getchar(int port)
41 {
42 	if (!port)
43 		return -1;
44 	while (!uart_charav(port));
45 	return ((char) inb(RBR(port)) & 0177);
46 }
47 
uart_putchar(int port,unsigned char c)48 static void uart_putchar(int port, unsigned char c)
49 {
50 	if (!port)
51 		return;
52 	if (c == '\n')
53 		uart_putchar(port, '\r');
54 	while (!(inb(LSR(port)) & 0x20));
55 	outb(c, THR(port));
56 }
57 
uart_init_line(int port,unsigned long baud)58 static void uart_init_line(int port, unsigned long baud)
59 {
60 	int i, baudconst;
61 
62 	if (!port)
63 		return;
64 
65 	switch (baud) {
66 	case 115200:
67 		baudconst = 1;
68 		break;
69 	case 57600:
70 		baudconst = 2;
71 		break;
72 	case 38400:
73 		baudconst = 3;
74 		break;
75 	case 19200:
76 		baudconst = 6;
77 		break;
78 	case 9600:
79 	default:
80 		baudconst = 12;
81 		break;
82 	}
83 
84 	outb(0x87, LCR(port));
85 	outb(0x00, DLM(port));
86 	outb(baudconst, DLL(port));
87 	outb(0x07, LCR(port));
88 	outb(0x0f, MCR(port));
89 
90 	for (i = 10; i > 0; i--) {
91 		if (inb(LSR(port)) == (unsigned int) 0)
92 			break;
93 		inb(RBR(port));
94 	}
95 }
96 
uart_init(int port,unsigned long speed)97 int uart_init(int port, unsigned long speed)
98 {
99 	if (port)
100 		uart_init_line(port, speed);
101 	return -1;
102 }
103 
serial_putchar(int c)104 static void serial_putchar(int c)
105 {
106 	uart_putchar(CONFIG_SERIAL_PORT, (unsigned char) (c & 0xff));
107 }
108 
serial_cls(void)109 static void serial_cls(void)
110 {
111 	serial_putchar(27);
112 	serial_putchar('[');
113 	serial_putchar('H');
114 	serial_putchar(27);
115 	serial_putchar('[');
116 	serial_putchar('J');
117 }
118 
119 #endif
120 
121 /* ******************************************************************
122  *          simple polling video/keyboard console functions
123  * ****************************************************************** */
124 
125 #ifdef CONFIG_DEBUG_CONSOLE_VGA
126 
127 /* raw vga text mode */
128 #define COLUMNS			80	/* The number of columns.  */
129 #define LINES			25	/* The number of lines.  */
130 #define ATTRIBUTE		7	/* The attribute of an character.  */
131 
132 #define VGA_BASE		0xB8000	/* The video memory address.  */
133 
134 /* VGA Index and Data Registers */
135 #define VGA_REG_INDEX    0x03D4	/* VGA index register */
136 #define VGA_REG_DATA     0x03D5	/* VGA data register */
137 
138 #define VGA_IDX_CURMSL   0x09	/* cursor maximum scan line */
139 #define VGA_IDX_CURSTART 0x0A	/* cursor start */
140 #define VGA_IDX_CUREND   0x0B	/* cursor end */
141 #define VGA_IDX_CURLO    0x0F	/* cursor position (low 8 bits) */
142 #define VGA_IDX_CURHI    0x0E	/* cursor position (high 8 bits) */
143 
144 /* Save the X and Y position.  */
145 static int xpos, ypos;
146 /* Point to the video memory.  */
147 static volatile unsigned char *video = (unsigned char *) VGA_BASE;
148 
video_initcursor(void)149 static void video_initcursor(void)
150 {
151 	u8 val;
152 	outb(VGA_IDX_CURMSL, VGA_REG_INDEX);
153 	val = inb(VGA_REG_DATA) & 0x1f;	/* maximum scan line -1 */
154 
155 	outb(VGA_IDX_CURSTART, VGA_REG_INDEX);
156 	outb(0, VGA_REG_DATA);
157 
158 	outb(VGA_IDX_CUREND, VGA_REG_INDEX);
159 	outb(val, VGA_REG_DATA);
160 }
161 
162 
163 
video_poscursor(unsigned int x,unsigned int y)164 static void video_poscursor(unsigned int x, unsigned int y)
165 {
166 	unsigned short pos;
167 
168 	/* Calculate new cursor position as a function of x and y */
169 	pos = (y * COLUMNS) + x;
170 
171 	/* Output the new position to VGA card */
172 	outb(VGA_IDX_CURLO, VGA_REG_INDEX);	/* output low 8 bits */
173 	outb((u8) (pos), VGA_REG_DATA);
174 	outb(VGA_IDX_CURHI, VGA_REG_INDEX);	/* output high 8 bits */
175 	outb((u8) (pos >> 8), VGA_REG_DATA);
176 
177 };
178 
179 
video_newline(void)180 static void video_newline(void)
181 {
182 	xpos = 0;
183 
184 	if (ypos < LINES - 1) {
185 		ypos++;
186 	} else {
187 		int i;
188 		memmove((void *) video, (void *) (video + 2 * COLUMNS),
189 			(LINES - 1) * COLUMNS * 2);
190 
191 		for (i = ((LINES - 1) * 2 * COLUMNS);
192 		     i < 2 * COLUMNS * LINES;) {
193 			video[i++] = 0;
194 			video[i++] = ATTRIBUTE;
195 		}
196 	}
197 
198 }
199 
200 /* Put the character C on the screen.  */
video_putchar(int c)201 static void video_putchar(int c)
202 {
203 	int p=1;
204 
205 	if (c == '\n' || c == '\r') {
206 		video_newline();
207 		return;
208 	}
209 
210 	if (c == '\b') {
211 		if (xpos) xpos--;
212 		c=' ';
213 		p=0;
214 	}
215 
216 
217 	if (xpos >= COLUMNS)
218 		video_newline();
219 
220 	*(video + (xpos + ypos * COLUMNS) * 2) = c & 0xFF;
221 	*(video + (xpos + ypos * COLUMNS) * 2 + 1) = ATTRIBUTE;
222 
223 	if (p)
224 		xpos++;
225 
226 	video_poscursor(xpos, ypos);
227 }
228 
video_cls(void)229 static void video_cls(void)
230 {
231 	int i;
232 
233 	for (i = 0; i < 2 * COLUMNS * LINES;) {
234 		video[i++] = 0;
235 		video[i++] = ATTRIBUTE;
236 	}
237 
238 
239 	xpos = 0;
240 	ypos = 0;
241 
242 	video_initcursor();
243 	video_poscursor(xpos, ypos);
244 }
245 
video_init(void)246 void video_init(void)
247 {
248 	video=phys_to_virt((unsigned char*)VGA_BASE);
249 }
250 
251 /*
252  *  keyboard driver
253  */
254 
255 static const char normal[] = {
256 	0x0, 0x1b, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-',
257 	'=', '\b', '\t', 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o',
258 	'p', '[', ']', 0xa, 0x0, 'a', 's', 'd', 'f', 'g', 'h', 'j',
259 	'k', 'l', ';', 0x27, 0x60, 0x0, 0x5c, 'z', 'x', 'c', 'v', 'b',
260 	'n', 'm', ',', '.', '/', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
261 	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
262 	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '0', 0x7f
263 };
264 
265 static const char shifted[] = {
266 	0x0, 0x1b, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_',
267 	'+', '\b', '\t', 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O',
268 	'P', '{', '}', 0xa, 0x0, 'A', 'S', 'D', 'F', 'G', 'H', 'J',
269 	'K', 'L', ':', 0x22, '~', 0x0, '|', 'Z', 'X', 'C', 'V', 'B',
270 	'N', 'M', '<', '>', '?', 0x0, '*', 0x0, ' ', 0x0, 0x0, 0x0,
271 	0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, '7', '8',
272 	'9', 0x0, '4', '5', '6', 0x0, '1', '2', '3', '0', 0x7f
273 };
274 
275 static int key_ext;
276 static int key_lshift = 0, key_rshift = 0, key_caps = 0;
277 
278 static char last_key;
279 
keyboard_cmd(unsigned char cmd,unsigned char val)280 static void keyboard_cmd(unsigned char cmd, unsigned char val)
281 {
282 	outb(cmd, 0x60);
283 	/* wait until keyboard controller accepts cmds: */
284 	while (inb(0x64) & 2);
285 	outb(val, 0x60);
286 	while (inb(0x64) & 2);
287 }
288 
keyboard_poll(void)289 static char keyboard_poll(void)
290 {
291 	unsigned int c;
292 	if (inb(0x64) & 1) {
293 		c = inb(0x60);
294 		switch (c) {
295 		case 0xe0:
296 			key_ext = 1;
297 			return 0;
298 		case 0x2a:
299 			key_lshift = 1;
300 			return 0;
301 		case 0x36:
302 			key_rshift = 1;
303 			return 0;
304 		case 0xaa:
305 			key_lshift = 0;
306 			return 0;
307 		case 0xb6:
308 			key_rshift = 0;
309 			return 0;
310 		case 0x3a:
311 			if (key_caps) {
312 				key_caps = 0;
313 				keyboard_cmd(0xed, 0);
314 			} else {
315 				key_caps = 1;
316 				keyboard_cmd(0xed, 4);	/* set caps led */
317 			}
318 			return 0;
319 		}
320 
321 		if (key_ext) {
322 			// void printk(const char *format, ...);
323 			printk("extended keycode: %x\n", c);
324 
325 			key_ext = 0;
326 			return 0;
327 		}
328 
329 		if (c & 0x80)	/* unhandled key release */
330 			return 0;
331 
332 		if (key_lshift || key_rshift)
333 			return key_caps ? normal[c] : shifted[c];
334 		else
335 			return key_caps ? shifted[c] : normal[c];
336 	}
337 	return 0;
338 }
339 
keyboard_dataready(void)340 static int keyboard_dataready(void)
341 {
342 	if (last_key)
343 		return 1;
344 
345 	last_key = keyboard_poll();
346 
347 	return (last_key != 0);
348 }
349 
keyboard_readdata(void)350 static unsigned char keyboard_readdata(void)
351 {
352 	char tmp;
353 	while (!keyboard_dataready());
354 	tmp = last_key;
355 	last_key = 0;
356 	return tmp;
357 }
358 #endif
359 
360 
361 /* ******************************************************************
362  *      common functions, implementing simple concurrent console
363  * ****************************************************************** */
364 
arch_putchar(int c)365 static int arch_putchar(int c)
366 {
367 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
368 	serial_putchar(c);
369 #endif
370 #ifdef CONFIG_DEBUG_CONSOLE_VGA
371 	video_putchar(c);
372 #endif
373 	return c;
374 }
375 
arch_availchar(void)376 static int arch_availchar(void)
377 {
378 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
379 	if (uart_charav(CONFIG_SERIAL_PORT))
380 		return 1;
381 #endif
382 #ifdef CONFIG_DEBUG_CONSOLE_VGA
383 	if (keyboard_dataready())
384 		return 1;
385 #endif
386 	return 0;
387 }
388 
arch_getchar(void)389 static int arch_getchar(void)
390 {
391 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
392 	if (uart_charav(CONFIG_SERIAL_PORT))
393 		return (uart_getchar(CONFIG_SERIAL_PORT));
394 #endif
395 #ifdef CONFIG_DEBUG_CONSOLE_VGA
396 	if (keyboard_dataready())
397 		return (keyboard_readdata());
398 #endif
399 	return 0;
400 }
401 
cls(void)402 void cls(void)
403 {
404 #ifdef CONFIG_DEBUG_CONSOLE_SERIAL
405 	serial_cls();
406 #endif
407 #ifdef CONFIG_DEBUG_CONSOLE_VGA
408 	video_cls();
409 #endif
410 }
411 
412 struct _console_ops arch_console_ops = {
413 	.putchar = arch_putchar,
414 	.availchar = arch_availchar,
415 	.getchar = arch_getchar
416 };
417 
418 #endif				// CONFIG_DEBUG_CONSOLE
419