vidconsole.c revision 85065
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 * From Id: probe_keyboard.c,v 1.13 1997/06/09 05:10:55 bde Exp 28 * 29 * $FreeBSD: head/sys/boot/pc98/libpc98/vidconsole.c 85065 2001-10-17 15:15:01Z nyan $ 30 */ 31 32#include <stand.h> 33#include <bootstrap.h> 34#include <btxv86.h> 35#include <machine/psl.h> 36#ifdef PC98 37#include <machine/cpufunc.h> 38#endif 39#include "libi386.h" 40 41#if KEYBOARD_PROBE 42#include <machine/cpufunc.h> 43 44static int probe_keyboard(void); 45#endif 46static void vidc_probe(struct console *cp); 47static int vidc_init(int arg); 48static void vidc_putchar(int c); 49static int vidc_getchar(void); 50static int vidc_ischar(void); 51 52static int vidc_started; 53 54#ifdef TERM_EMU 55#define MAXARGS 8 56#define DEFAULT_FGCOLOR 7 57#define DEFAULT_BGCOLOR 0 58 59void end_term(void); 60void bail_out(int c); 61void vidc_term_emu(int c); 62void get_pos(void); 63void curs_move(int x, int y); 64void write_char(int c, int fg, int bg); 65void scroll_up(int rows, int fg, int bg); 66void CD(void); 67void CM(void); 68void HO(void); 69 70static int args[MAXARGS], argc; 71static int fg_c, bg_c, curx, cury; 72static int esc; 73#endif 74 75#ifdef PC98 76static unsigned short *crtat, *Crtat; 77static int row = 25, col = 80; 78#ifdef TERM_EMU 79static u_int8_t ibmpc_to_pc98[256] = { 80 0x01, 0x21, 0x81, 0xa1, 0x41, 0x61, 0xc1, 0xe1, 81 0x09, 0x29, 0x89, 0xa9, 0x49, 0x69, 0xc9, 0xe9, 82 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 83 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 0x25, 84 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 85 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 0x85, 86 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 87 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 0xa5, 88 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 89 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 0x45, 90 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 91 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 0x65, 92 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 93 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 0xc5, 94 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 95 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 0xe5, 96 97 0x03, 0x23, 0x83, 0xa3, 0x43, 0x63, 0xc3, 0xe3, 98 0x0b, 0x2b, 0x8b, 0xab, 0x4b, 0x6b, 0xcb, 0xeb, 99 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 100 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 0x2f, 101 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 102 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 0x8f, 103 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 104 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 0xaf, 105 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 106 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 0x4f, 107 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 108 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 0x6f, 109 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 110 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 0xcf, 111 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 112 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 0xef, 113}; 114#define at2pc98(fg_at, bg_at) ibmpc_to_pc98[((bg_at) << 4) | (fg_at)] 115#endif /* TERM_EMU */ 116#endif /* PC98 */ 117 118struct console vidconsole = { 119 "vidconsole", 120 "internal video/keyboard", 121 0, 122 vidc_probe, 123 vidc_init, 124 vidc_putchar, 125 vidc_getchar, 126 vidc_ischar 127}; 128 129static void 130vidc_probe(struct console *cp) 131{ 132 133 /* look for a keyboard */ 134#if KEYBOARD_PROBE 135 if (probe_keyboard()) 136#endif 137 { 138 139 cp->c_flags |= C_PRESENTIN; 140 } 141 142 /* XXX for now, always assume we can do BIOS screen output */ 143 cp->c_flags |= C_PRESENTOUT; 144} 145 146static int 147vidc_init(int arg) 148{ 149 int i; 150#ifdef PC98 151 int hw_cursor; 152#endif 153 154 if (vidc_started && arg == 0) 155 return (0); 156 vidc_started = 1; 157#ifdef PC98 158 Crtat = (unsigned short *)PTOV(0xA0000); 159 while ((inb(0x60) & 0x04) == 0) 160 ; 161 outb(0x62, 0xe0); 162 while ((inb(0x60) & 0x01) == 0) 163 ; 164 hw_cursor = inb(0x62); 165 hw_cursor |= (inb(0x62) << 8); 166 inb(0x62); 167 inb(0x62); 168 inb(0x62); 169 crtat = Crtat + hw_cursor; 170#endif 171#ifdef TERM_EMU 172 /* Init terminal emulator */ 173 end_term(); 174 get_pos(); 175 curs_move(curx, cury); 176 fg_c = DEFAULT_FGCOLOR; 177 bg_c = DEFAULT_BGCOLOR; 178#endif 179 for (i = 0; i < 10 && vidc_ischar(); i++) 180 (void)vidc_getchar(); 181 return (0); /* XXX reinit? */ 182} 183 184#ifdef PC98 185static void 186beep(void) 187{ 188 189 outb(0x37, 6); 190 delay(40000); 191 outb(0x37, 7); 192} 193#endif 194 195#if 0 196static void 197vidc_biosputchar(int c) 198{ 199#ifdef PC98 200 unsigned short *cp; 201 int i, pos; 202 203#ifdef TERM_EMU 204 *crtat = (c == 0x5c ? 0xfc : c); 205 *(crtat + 0x1000) = at2pc98(fg, bg); 206#else 207 switch(c) { 208 case '\b': 209 crtat--; 210 break; 211 case '\r': 212 crtat -= (crtat - Crtat) % col; 213 break; 214 case '\n': 215 crtat += col; 216 break; 217 default: 218 *crtat = (c == 0x5c ? 0xfc : c); 219 *(crtat++ + 0x1000) = 0xe1; 220 break; 221 } 222 223 if (crtat >= Crtat + col * row) { 224 cp = Crtat; 225 for (i = 1; i < row; i++) { 226 bcopy((void *)(cp + col), (void *)cp, col * 2); 227 cp += col; 228 } 229 for (i = 0; i < col; i++) { 230 *cp++ = ' '; 231 } 232 crtat -= col; 233 } 234 pos = crtat - Crtat; 235 while ((inb(0x60) & 0x04) == 0) {} 236 outb(0x62, 0x49); 237 outb(0x60, pos & 0xff); 238 outb(0x60, pos >> 8); 239#endif 240#else 241 242 v86.ctl = 0; 243 v86.addr = 0x10; 244 v86.eax = 0xe00 | (c & 0xff); 245 v86.ebx = 0x7; 246 v86int(); 247#endif 248} 249#endif 250 251static void 252vidc_rawputchar(int c) 253{ 254 int i; 255 256 if (c == '\t') 257 /* lame tab expansion */ 258 for (i = 0; i < 8; i++) 259 vidc_rawputchar(' '); 260 else { 261#if !defined(TERM_EMU) && !defined(PC98) 262 vidc_biosputchar(c); 263#else 264 /* Emulate AH=0eh (teletype output) */ 265 switch(c) { 266 case '\a': 267#ifdef PC98 268 beep(); 269#else 270 vidc_biosputchar(c); 271#endif 272 return; 273 case '\r': 274 curx = 0; 275 curs_move(curx, cury); 276 return; 277 case '\n': 278 cury++; 279 if (cury > 24) { 280 scroll_up(1, fg_c, bg_c); 281 cury--; 282 } else { 283 curs_move(curx, cury); 284 } 285 return; 286 case '\b': 287 if (curx > 0) { 288 curx--; 289 curs_move(curx, cury); 290 /* write_char(' ', fg_c, bg_c); XXX destructive(!) */ 291 return; 292 } 293 return; 294 default: 295 write_char(c, fg_c, bg_c); 296 curx++; 297 if (curx > 79) { 298 curx = 0; 299 cury++; 300 } 301 if (cury > 24) { 302 curx = 0; 303 scroll_up(1, fg_c, bg_c); 304 cury--; 305 } 306 } 307 curs_move(curx, cury); 308#endif 309 } 310} 311 312#ifdef TERM_EMU 313 314/* Get cursor position on the screen. Result is in edx. Sets 315 * curx and cury appropriately. 316 */ 317void 318get_pos(void) 319{ 320#ifdef PC98 321 int pos = crtat - Crtat; 322 323 curx = pos % col; 324 cury = pos / col; 325#else 326 327 v86.ctl = 0; 328 v86.addr = 0x10; 329 v86.eax = 0x0300; 330 v86.ebx = 0x0; 331 v86int(); 332 curx = v86.edx & 0x00ff; 333 cury = (v86.edx & 0xff00) >> 8; 334#endif 335} 336 337/* Move cursor to x rows and y cols (0-based). */ 338void 339curs_move(int x, int y) 340{ 341#ifdef PC98 342 int pos; 343 344 pos = x + y * col; 345 crtat = Crtat + pos; 346 pos = crtat - Crtat; 347 while((inb(0x60) & 0x04) == 0) {} 348 outb(0x62, 0x49); 349 outb(0x60, pos & 0xff); 350 outb(0x60, pos >> 8); 351 curx = x; 352 cury = y; 353#define isvisible(c) (((c) >= 32) && ((c) < 255)) 354 if (!isvisible(*crtat & 0x00ff)) { 355 write_char(' ', fg_c, bg_c); 356 } 357#else 358 359 v86.ctl = 0; 360 v86.addr = 0x10; 361 v86.eax = 0x0200; 362 v86.ebx = 0x0; 363 v86.edx = ((0x00ff & y) << 8) + (0x00ff & x); 364 v86int(); 365 curx = x; 366 cury = y; 367 /* If there is ctrl char at this position, cursor would be invisible. 368 * Make it a space instead. 369 */ 370 v86.ctl = 0; 371 v86.addr = 0x10; 372 v86.eax = 0x0800; 373 v86.ebx = 0x0; 374 v86int(); 375#define isvisible(c) (((c) >= 32) && ((c) < 255)) 376 if (!isvisible(v86.eax & 0x00ff)) { 377 write_char(' ', fg_c, bg_c); 378 } 379#endif 380} 381 382/* Scroll up the whole window by a number of rows. If rows==0, 383 * clear the window. fg and bg are attributes for the new lines 384 * inserted in the window. 385 */ 386void 387scroll_up(int rows, int fgcol, int bgcol) 388{ 389#ifdef PC98 390 unsigned short *cp; 391 int i; 392 393 if (rows == 0) 394 rows = 25; 395 cp = Crtat; 396 for (i = rows; i < row; i++) { 397 bcopy((void *)(cp + col), (void *)cp, col * 2); 398 cp += col; 399 } 400 for (i = 0; i < col; i++) { 401 *(cp + 0x1000) = at2pc98(fgcol, bgcol); 402 *cp++ = ' '; 403 } 404#else 405 406 if (rows == 0) 407 rows = 25; 408 v86.ctl = 0; 409 v86.addr = 0x10; 410 v86.eax = 0x0600 + (0x00ff & rows); 411 v86.ebx = (bgcol << 12) + (fgcol << 8); 412 v86.ecx = 0x0; 413 v86.edx = 0x184f; 414 v86int(); 415#endif 416} 417 418/* Write character and attribute at cursor position. */ 419void 420write_char(int c, int fgcol, int bgcol) 421{ 422 423#ifdef PC98 424 *crtat = (c == 0x5c ? 0xfc : c); 425 *(crtat + 0x1000) = at2pc98(fgcol, bgcol); 426#else 427 v86.ctl = 0; 428 v86.addr = 0x10; 429 v86.eax = 0x0900 + (0x00ff & c); 430 v86.ebx = (bgcol << 4) + fgcol; 431 v86.ecx = 0x1; 432 v86int(); 433#endif 434} 435 436/**************************************************************/ 437/* 438 * Screen manipulation functions. They use accumulated data in 439 * args[] and argc variables. 440 * 441 */ 442 443/* Clear display from current position to end of screen */ 444void 445CD(void) 446{ 447#ifdef PC98 448 int pos; 449 450 get_pos(); 451 for (pos = 0; crtat + pos <= Crtat + col * row; pos++) { 452 *(crtat + pos) = ' '; 453 *(crtat + pos + 0x1000) = at2pc98(fg_c, bg_c); 454 } 455 end_term(); 456#else 457 458 get_pos(); 459 if (curx > 0) { 460 v86.ctl = 0; 461 v86.addr = 0x10; 462 v86.eax = 0x0600; 463 v86.ebx = (bg_c << 4) + fg_c; 464 v86.ecx = (cury << 8) + curx; 465 v86.edx = (cury << 8) + 79; 466 v86int(); 467 if (++cury > 24) { 468 end_term(); 469 return; 470 } 471 } 472 v86.ctl = 0; 473 v86.addr = 0x10; 474 v86.eax = 0x0600; 475 v86.ebx = (bg_c << 4) + fg_c; 476 v86.ecx = (cury << 8) + 0; 477 v86.edx = (24 << 8) + 79; 478 v86int(); 479 end_term(); 480#endif 481} 482 483/* Absolute cursor move to args[0] rows and args[1] columns 484 * (the coordinates are 1-based). 485 */ 486void 487CM(void) 488{ 489 490 if (args[0] > 0) 491 args[0]--; 492 if (args[1] > 0) 493 args[1]--; 494 curs_move(args[1], args[0]); 495 end_term(); 496} 497 498/* Home cursor (left top corner) */ 499void 500HO(void) 501{ 502 503 argc = 1; 504 args[0] = args[1] = 1; 505 CM(); 506} 507 508/* Clear internal state of the terminal emulation code */ 509void 510end_term(void) 511{ 512 513 esc = 0; 514 argc = -1; 515} 516 517/* Gracefully exit ESC-sequence processing in case of misunderstanding */ 518void 519bail_out(int c) 520{ 521 char buf[16], *ch; 522 int i; 523 524 if (esc) { 525 vidc_rawputchar('\033'); 526 if (esc != '\033') 527 vidc_rawputchar(esc); 528 for (i = 0; i <= argc; ++i) { 529 sprintf(buf, "%d", args[i]); 530 ch = buf; 531 while (*ch) 532 vidc_rawputchar(*ch++); 533 } 534 } 535 vidc_rawputchar(c); 536 end_term(); 537} 538 539static void 540get_arg(c) 541{ 542 543 if (argc < 0) 544 argc = 0; 545 args[argc] *= 10; 546 args[argc] += c - '0'; 547} 548 549/* Emulate basic capabilities of cons25 terminal */ 550void 551vidc_term_emu(int c) 552{ 553 static int ansi_col[] = { 554 0, 4, 2, 6, 1, 5, 3, 7, 555 }; 556 int t; 557 int i; 558 559 switch (esc) { 560 case 0: 561 switch (c) { 562 case '\033': 563 esc = c; 564 break; 565 default: 566 vidc_rawputchar(c); 567 break; 568 } 569 break; 570 571 case '\033': 572 switch (c) { 573 case '[': 574 esc = c; 575 args[0] = 0; 576 argc = -1; 577 break; 578 default: 579 bail_out(c); 580 break; 581 } 582 break; 583 584 case '[': 585 switch (c) { 586 case ';': 587 if (argc < 0) /* XXX */ 588 argc = 0; 589 else if (argc + 1 >= MAXARGS) 590 bail_out(c); 591 else 592 args[++argc] = 0; 593 break; 594 case 'H': 595 if (argc < 0) 596 HO(); 597 else if (argc == 1) 598 CM(); 599 else 600 bail_out(c); 601 break; 602 case 'J': 603 if (argc < 0) 604 CD(); 605 else 606 bail_out(c); 607 break; 608 case 'm': 609 if (argc < 0) { 610 fg_c = DEFAULT_FGCOLOR; 611 bg_c = DEFAULT_BGCOLOR; 612 } 613 for (i = 0; i <= argc; ++i) { 614 switch (args[i]) { 615 case 0: /* back to normal */ 616 fg_c = DEFAULT_FGCOLOR; 617 bg_c = DEFAULT_BGCOLOR; 618 break; 619 case 1: /* bold */ 620 fg_c |= 0x8; 621 break; 622 case 4: /* underline */ 623 case 5: /* blink */ 624 bg_c |= 0x8; 625 break; 626 case 7: /* reverse */ 627 t = fg_c; 628 fg_c = bg_c; 629 bg_c = t; 630 break; 631 case 30: case 31: case 32: case 33: 632 case 34: case 35: case 36: case 37: 633 fg_c = ansi_col[args[i] - 30]; 634 break; 635 case 39: /* normal */ 636 fg_c = DEFAULT_FGCOLOR; 637 break; 638 case 40: case 41: case 42: case 43: 639 case 44: case 45: case 46: case 47: 640 bg_c = ansi_col[args[i] - 40]; 641 break; 642 case 49: /* normal */ 643 bg_c = DEFAULT_BGCOLOR; 644 break; 645 } 646 } 647 end_term(); 648 break; 649 default: 650 if (isdigit(c)) 651 get_arg(c); 652 else 653 bail_out(c); 654 break; 655 } 656 break; 657 658 default: 659 bail_out(c); 660 break; 661 } 662} 663#endif 664 665static void 666vidc_putchar(int c) 667{ 668#ifdef TERM_EMU 669 vidc_term_emu(c); 670#else 671 vidc_rawputchar(c); 672#endif 673} 674 675static int 676vidc_getchar(void) 677{ 678 679 if (vidc_ischar()) { 680 v86.ctl = 0; 681#ifdef PC98 682 v86.addr = 0x18; 683#else 684 v86.addr = 0x16; 685#endif 686 v86.eax = 0x0; 687 v86int(); 688 return (v86.eax & 0xff); 689 } else { 690 return (-1); 691 } 692} 693 694static int 695vidc_ischar(void) 696{ 697 698#ifdef PC98 699 v86.ctl = 0; 700 v86.addr = 0x18; 701 v86.eax = 0x100; 702 v86int(); 703 return ((v86.ebx >> 8) & 0x1); 704#else 705 v86.ctl = V86_FLAGS; 706 v86.addr = 0x16; 707 v86.eax = 0x100; 708 v86int(); 709 return (!(v86.efl & PSL_Z)); 710#endif 711} 712 713#if KEYBOARD_PROBE 714 715#ifdef PC98 716static int 717probe_keyboard(void) 718{ 719 return (*(u_char *)PTOV(0xA1481) & 0x48); 720} 721#else /* PC98 */ 722#define PROBE_MAXRETRY 5 723#define PROBE_MAXWAIT 400 724#define IO_DUMMY 0x84 725#define IO_KBD 0x060 /* 8042 Keyboard */ 726 727/* selected defines from kbdio.h */ 728#define KBD_STATUS_PORT 4 /* status port, read */ 729#define KBD_DATA_PORT 0 /* data port, read/write 730 * also used as keyboard command 731 * and mouse command port 732 */ 733#define KBDC_ECHO 0x00ee 734#define KBDS_ANY_BUFFER_FULL 0x0001 735#define KBDS_INPUT_BUFFER_FULL 0x0002 736#define KBD_ECHO 0x00ee 737 738/* 7 microsec delay necessary for some keyboard controllers */ 739static void 740delay7(void) 741{ 742 /* 743 * I know this is broken, but no timer is available yet at this stage... 744 * See also comments in `delay1ms()'. 745 */ 746 inb(IO_DUMMY); inb(IO_DUMMY); 747 inb(IO_DUMMY); inb(IO_DUMMY); 748 inb(IO_DUMMY); inb(IO_DUMMY); 749} 750 751/* 752 * This routine uses an inb to an unused port, the time to execute that 753 * inb is approximately 1.25uS. This value is pretty constant across 754 * all CPU's and all buses, with the exception of some PCI implentations 755 * that do not forward this I/O address to the ISA bus as they know it 756 * is not a valid ISA bus address, those machines execute this inb in 757 * 60 nS :-(. 758 * 759 */ 760static void 761delay1ms(void) 762{ 763 int i = 800; 764 while (--i >= 0) 765 (void)inb(0x84); 766} 767 768/* 769 * We use the presence/absence of a keyboard to determine whether the internal 770 * console can be used for input. 771 * 772 * Perform a simple test on the keyboard; issue the ECHO command and see 773 * if the right answer is returned. We don't do anything as drastic as 774 * full keyboard reset; it will be too troublesome and take too much time. 775 */ 776static int 777probe_keyboard(void) 778{ 779 int retry = PROBE_MAXRETRY; 780 int wait; 781 int i; 782 783 while (--retry >= 0) { 784 /* flush any noise */ 785 while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) { 786 delay7(); 787 inb(IO_KBD + KBD_DATA_PORT); 788 delay1ms(); 789 } 790 791 /* wait until the controller can accept a command */ 792 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 793 if (((i = inb(IO_KBD + KBD_STATUS_PORT)) 794 & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0) 795 break; 796 if (i & KBDS_ANY_BUFFER_FULL) { 797 delay7(); 798 inb(IO_KBD + KBD_DATA_PORT); 799 } 800 delay1ms(); 801 } 802 if (wait <= 0) 803 continue; 804 805 /* send the ECHO command */ 806 outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO); 807 808 /* wait for a response */ 809 for (wait = PROBE_MAXWAIT; wait > 0; --wait) { 810 if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) 811 break; 812 delay1ms(); 813 } 814 if (wait <= 0) 815 continue; 816 817 delay7(); 818 i = inb(IO_KBD + KBD_DATA_PORT); 819#ifdef PROBE_KBD_BEBUG 820 printf("probe_keyboard: got 0x%x.\n", i); 821#endif 822 if (i == KBD_ECHO) { 823 /* got the right answer */ 824 return (0); 825 } 826 } 827 828 return (1); 829} 830#endif /* PC98 */ 831#endif /* KEYBOARD_PROBE */ 832