Deleted Added
sdiff udiff text old ( 145069 ) new ( 146011 )
full compact
1/*-
2 * Copyright (c) 1998 Michael Smith (msmith@freebsd.org)
3 * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
4 * All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 * Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp
28 */
29
30#include <sys/cdefs.h>
31__FBSDID("$FreeBSD: head/sys/boot/pc98/libpc98/vidconsole.c 146011 2005-05-08 14:17:28Z nyan $");
32
33#include <stand.h>
34#include <bootstrap.h>
35#include <btxv86.h>
36#include <machine/psl.h>
37#include <machine/cpufunc.h>
38#include "libi386.h"
39
40#if KEYBOARD_PROBE
41#include <machine/cpufunc.h>
42
43static int probe_keyboard(void);
44#endif
45static void vidc_probe(struct console *cp);
46static int vidc_init(int arg);
47static void vidc_putchar(int c);
48static int vidc_getchar(void);
49static int vidc_ischar(void);
50
51static int vidc_started;
52
53#ifdef TERM_EMU
54#define MAXARGS 8
55#define DEFAULT_FGCOLOR 7
56#define DEFAULT_BGCOLOR 0
57
58void end_term(void);
59void bail_out(int c);
60void vidc_term_emu(int c);
61void get_pos(void);
62void curs_move(int x, int y);
63void write_char(int c, int fg, int bg);
64void scroll_up(int rows, int fg, int bg);
65void CD(void);
66void CM(void);
67void HO(void);
68
69static int args[MAXARGS], argc;
70static int fg_c, bg_c, curx, cury;
71static int esc;
72#endif
73
74static unsigned short *crtat, *Crtat;
75static int row = 25, col = 80;
76#ifdef TERM_EMU
77static u_int8_t ibmpc_to_pc98[256] = {
78 0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1,
79 0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9,
80 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
81 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25,
82 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
83 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85,
84 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
85 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5,
86 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
87 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45,
88 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
89 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65,
90 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
91 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5,
92 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
93 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5,
94
95 0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3,
96 0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb,
97 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
98 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f,
99 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
100 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f,
101 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
102 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf,
103 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
104 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f,
105 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
106 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f,
107 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
108 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf,
109 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
110 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef,
111};
112#define at2pc98(fg_at, bg_at) ibmpc_to_pc98[((bg_at) << 4) | (fg_at)]
113#endif /* TERM_EMU */
114
115struct console vidconsole = {
116 "vidconsole",
117 "internal video/keyboard",
118 0,
119 vidc_probe,
120 vidc_init,
121 vidc_putchar,
122 vidc_getchar,
123 vidc_ischar
124};
125
126static void
127vidc_probe(struct console *cp)
128{
129
130 /* look for a keyboard */
131#if KEYBOARD_PROBE
132 if (probe_keyboard())
133#endif
134 {
135
136 cp->c_flags |= C_PRESENTIN;
137 }
138
139 /* XXX for now, always assume we can do BIOS screen output */
140 cp->c_flags |= C_PRESENTOUT;
141}
142
143static int
144vidc_init(int arg)
145{
146 int i, hw_cursor;
147
148 if (vidc_started && arg == 0)
149 return (0);
150 vidc_started = 1;
151 Crtat = (unsigned short *)PTOV(0xA0000);
152 while ((inb(0x60) & 0x04) == 0)
153 ;
154 outb(0x62, 0xe0);
155 while ((inb(0x60) & 0x01) == 0)
156 ;
157 hw_cursor = inb(0x62);
158 hw_cursor |= (inb(0x62) << 8);
159 inb(0x62);
160 inb(0x62);
161 inb(0x62);
162 crtat = Crtat + hw_cursor;
163#ifdef TERM_EMU
164 /* Init terminal emulator */
165 end_term();
166 get_pos();
167 curs_move(curx, cury);
168 fg_c = DEFAULT_FGCOLOR;
169 bg_c = DEFAULT_BGCOLOR;
170#endif
171 for (i = 0; i < 10 && vidc_ischar(); i++)
172 (void)vidc_getchar();
173 return (0); /* XXX reinit? */
174}
175
176static void
177beep(void)
178{
179
180 outb(0x37, 6);
181 delay(40000);
182 outb(0x37, 7);
183}
184
185#if 0
186static void
187vidc_biosputchar(int c)
188{
189 unsigned short *cp;
190 int i, pos;
191
192#ifdef TERM_EMU
193 *crtat = (c == 0x5c ? 0xfc : c);
194 *(crtat + 0x1000) = at2pc98(fg, bg);
195#else
196 switch(c) {
197 case '\b':
198 crtat--;
199 break;
200 case '\r':
201 crtat -= (crtat - Crtat) % col;
202 break;
203 case '\n':
204 crtat += col;
205 break;
206 default:
207 *crtat = (c == 0x5c ? 0xfc : c);
208 *(crtat++ + 0x1000) = 0xe1;
209 break;
210 }
211
212 if (crtat >= Crtat + col * row) {
213 cp = Crtat;
214 for (i = 1; i < row; i++) {
215 bcopy((void *)(cp + col), (void *)cp, col * 2);
216 cp += col;
217 }
218 for (i = 0; i < col; i++) {
219 *cp++ = ' ';
220 }
221 crtat -= col;
222 }
223 pos = crtat - Crtat;
224 while ((inb(0x60) & 0x04) == 0) {}
225 outb(0x62, 0x49);
226 outb(0x60, pos & 0xff);
227 outb(0x60, pos >> 8);
228#endif
229}
230#endif
231
232static void
233vidc_rawputchar(int c)
234{
235 int i;
236
237 if (c == '\t')
238 /* lame tab expansion */
239 for (i = 0; i < 8; i++)
240 vidc_rawputchar(' ');
241 else {
242 /* Emulate AH=0eh (teletype output) */
243 switch(c) {
244 case '\a':
245 beep();
246 return;
247 case '\r':
248 curx = 0;
249 curs_move(curx, cury);
250 return;
251 case '\n':
252 cury++;
253 if (cury > 24) {
254 scroll_up(1, fg_c, bg_c);
255 cury--;
256 } else {
257 curs_move(curx, cury);
258 }
259 return;
260 case '\b':
261 if (curx > 0) {
262 curx--;
263 curs_move(curx, cury);
264 /* write_char(' ', fg_c, bg_c); XXX destructive(!) */
265 return;
266 }
267 return;
268 default:
269 write_char(c, fg_c, bg_c);
270 curx++;
271 if (curx > 79) {
272 curx = 0;
273 cury++;
274 }
275 if (cury > 24) {
276 curx = 0;
277 scroll_up(1, fg_c, bg_c);
278 cury--;
279 }
280 }
281 curs_move(curx, cury);
282 }
283}
284
285#ifdef TERM_EMU
286
287/* Get cursor position on the screen. Result is in edx. Sets
288 * curx and cury appropriately.
289 */
290void
291get_pos(void)
292{
293 int pos = crtat - Crtat;
294
295 curx = pos % col;
296 cury = pos / col;
297}
298
299/* Move cursor to x rows and y cols (0-based). */
300void
301curs_move(int x, int y)
302{
303 int pos;
304
305 pos = x + y * col;
306 crtat = Crtat + pos;
307 pos = crtat - Crtat;
308 while((inb(0x60) & 0x04) == 0) {}
309 outb(0x62, 0x49);
310 outb(0x60, pos & 0xff);
311 outb(0x60, pos >> 8);
312 curx = x;
313 cury = y;
314#define isvisible(c) (((c) >= 32) && ((c) < 255))
315 if (!isvisible(*crtat & 0x00ff)) {
316 write_char(' ', fg_c, bg_c);
317 }
318}
319
320/* Scroll up the whole window by a number of rows. If rows==0,
321 * clear the window. fg and bg are attributes for the new lines
322 * inserted in the window.
323 */
324void
325scroll_up(int rows, int fgcol, int bgcol)
326{
327 unsigned short *cp;
328 int i;
329
330 if (rows == 0)
331 rows = 25;
332 cp = Crtat;
333 for (i = rows; i < row; i++) {
334 bcopy((void *)(cp + col), (void *)cp, col * 2);
335 cp += col;
336 }
337 for (i = 0; i < col; i++) {
338 *(cp + 0x1000) = at2pc98(fgcol, bgcol);
339 *cp++ = ' ';
340 }
341}
342
343/* Write character and attribute at cursor position. */
344void
345write_char(int c, int fgcol, int bgcol)
346{
347
348 *crtat = (c == 0x5c ? 0xfc : (c & 0xff));
349 *(crtat + 0x1000) = at2pc98(fgcol, bgcol);
350}
351
352/**************************************************************/
353/*
354 * Screen manipulation functions. They use accumulated data in
355 * args[] and argc variables.
356 *
357 */
358
359/* Clear display from current position to end of screen */
360void
361CD(void)
362{
363 int pos;
364
365 get_pos();
366 for (pos = 0; crtat + pos <= Crtat + col * row; pos++) {
367 *(crtat + pos) = ' ';
368 *(crtat + pos + 0x1000) = at2pc98(fg_c, bg_c);
369 }
370 end_term();
371}
372
373/* Absolute cursor move to args[0] rows and args[1] columns
374 * (the coordinates are 1-based).
375 */
376void
377CM(void)
378{
379
380 if (args[0] > 0)
381 args[0]--;
382 if (args[1] > 0)
383 args[1]--;
384 curs_move(args[1], args[0]);
385 end_term();
386}
387
388/* Home cursor (left top corner) */
389void
390HO(void)
391{
392
393 argc = 1;
394 args[0] = args[1] = 1;
395 CM();
396}
397
398/* Clear internal state of the terminal emulation code */
399void
400end_term(void)
401{
402
403 esc = 0;
404 argc = -1;
405}
406
407/* Gracefully exit ESC-sequence processing in case of misunderstanding */
408void
409bail_out(int c)
410{
411 char buf[16], *ch;
412 int i;
413
414 if (esc) {
415 vidc_rawputchar('\033');
416 if (esc != '\033')
417 vidc_rawputchar(esc);
418 for (i = 0; i <= argc; ++i) {
419 sprintf(buf, "%d", args[i]);
420 ch = buf;
421 while (*ch)
422 vidc_rawputchar(*ch++);
423 }
424 }
425 vidc_rawputchar(c);
426 end_term();
427}
428
429static void
430get_arg(int c)
431{
432
433 if (argc < 0)
434 argc = 0;
435 args[argc] *= 10;
436 args[argc] += c - '0';
437}
438
439/* Emulate basic capabilities of cons25 terminal */
440void
441vidc_term_emu(int c)
442{
443 static int ansi_col[] = {
444 0, 4, 2, 6, 1, 5, 3, 7,
445 };
446 int t;
447 int i;
448
449 switch (esc) {
450 case 0:
451 switch (c) {
452 case '\033':
453 esc = c;
454 break;
455 default:
456 vidc_rawputchar(c);
457 break;
458 }
459 break;
460
461 case '\033':
462 switch (c) {
463 case '[':
464 esc = c;
465 args[0] = 0;
466 argc = -1;
467 break;
468 default:
469 bail_out(c);
470 break;
471 }
472 break;
473
474 case '[':
475 switch (c) {
476 case ';':
477 if (argc < 0) /* XXX */
478 argc = 0;
479 else if (argc + 1 >= MAXARGS)
480 bail_out(c);
481 else
482 args[++argc] = 0;
483 break;
484 case 'H':
485 if (argc < 0)
486 HO();
487 else if (argc == 1)
488 CM();
489 else
490 bail_out(c);
491 break;
492 case 'J':
493 if (argc < 0)
494 CD();
495 else
496 bail_out(c);
497 break;
498 case 'm':
499 if (argc < 0) {
500 fg_c = DEFAULT_FGCOLOR;
501 bg_c = DEFAULT_BGCOLOR;
502 }
503 for (i = 0; i <= argc; ++i) {
504 switch (args[i]) {
505 case 0: /* back to normal */
506 fg_c = DEFAULT_FGCOLOR;
507 bg_c = DEFAULT_BGCOLOR;
508 break;
509 case 1: /* bold */
510 fg_c |= 0x8;
511 break;
512 case 4: /* underline */
513 case 5: /* blink */
514 bg_c |= 0x8;
515 break;
516 case 7: /* reverse */
517 t = fg_c;
518 fg_c = bg_c;
519 bg_c = t;
520 break;
521 case 30: case 31: case 32: case 33:
522 case 34: case 35: case 36: case 37:
523 fg_c = ansi_col[args[i] - 30];
524 break;
525 case 39: /* normal */
526 fg_c = DEFAULT_FGCOLOR;
527 break;
528 case 40: case 41: case 42: case 43:
529 case 44: case 45: case 46: case 47:
530 bg_c = ansi_col[args[i] - 40];
531 break;
532 case 49: /* normal */
533 bg_c = DEFAULT_BGCOLOR;
534 break;
535 }
536 }
537 end_term();
538 break;
539 default:
540 if (isdigit(c))
541 get_arg(c);
542 else
543 bail_out(c);
544 break;
545 }
546 break;
547
548 default:
549 bail_out(c);
550 break;
551 }
552}
553#endif
554
555static void
556vidc_putchar(int c)
557{
558#ifdef TERM_EMU
559 vidc_term_emu(c);
560#else
561 vidc_rawputchar(c);
562#endif
563}
564
565static int
566vidc_getchar(void)
567{
568
569 if (vidc_ischar()) {
570 v86.ctl = 0;
571 v86.addr = 0x18;
572 v86.eax = 0x0;
573 v86int();
574 return (v86.eax & 0xff);
575 } else {
576 return (-1);
577 }
578}
579
580static int
581vidc_ischar(void)
582{
583
584 v86.ctl = 0;
585 v86.addr = 0x18;
586 v86.eax = 0x100;
587 v86int();
588 return ((v86.ebx >> 8) & 0x1);
589}
590
591#if KEYBOARD_PROBE
592static int
593probe_keyboard(void)
594{
595 return (*(u_char *)PTOV(0xA1481) & 0x48);
596}
597#endif /* KEYBOARD_PROBE */