vidconsole.c revision 225736
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: stable/9/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 */ 598