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