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