Remove !_KERNEL parts.
[dragonfly.git] / sys / boot / pc98 / libpc98 / vidconsole.c
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  * $FreeBSD: src/sys/boot/pc98/libpc98/vidconsole.c,v 1.11 2003/09/08 09:11:20 obrien Exp $
29  * $DragonFly: src/sys/boot/pc98/libpc98/Attic/vidconsole.c,v 1.3 2003/11/10 06:08:39 dillon Exp $
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
44 static int      probe_keyboard(void);
45 #endif
46 static void     vidc_probe(struct console *cp);
47 static int      vidc_init(int arg);
48 static void     vidc_putchar(int c);
49 static int      vidc_getchar(void);
50 static int      vidc_ischar(void);
51
52 static int      vidc_started;
53
54 #ifdef TERM_EMU
55 #define MAXARGS         8
56 #define DEFAULT_FGCOLOR 7
57 #define DEFAULT_BGCOLOR 0
58
59 void            end_term(void);
60 void            bail_out(int c);
61 void            vidc_term_emu(int c);
62 void            get_pos(void);
63 void            curs_move(int x, int y);
64 void            write_char(int c, int fg, int bg);
65 void            scroll_up(int rows, int fg, int bg);
66 void            CD(void);
67 void            CM(void);
68 void            HO(void);
69
70 static int      args[MAXARGS], argc;
71 static int      fg_c, bg_c, curx, cury;
72 static int      esc;
73 #endif
74
75 #ifdef PC98
76 static unsigned short *crtat, *Crtat;
77 static int row = 25, col = 80;
78 #ifdef TERM_EMU
79 static 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
118 struct 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
129 static void
130 vidc_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
146 static int
147 vidc_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
185 static void
186 beep(void)
187 {
188
189         outb(0x37, 6);
190         delay(40000);
191         outb(0x37, 7);
192 }
193 #endif
194
195 #if 0
196 static void
197 vidc_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
251 static void
252 vidc_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  */
317 void
318 get_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). */
338 void
339 curs_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  */
386 void
387 scroll_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. */
419 void
420 write_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 */
444 void
445 CD(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  */
486 void
487 CM(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) */
499 void
500 HO(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 */
509 void
510 end_term(void)
511 {
512
513     esc = 0;
514     argc = -1;
515 }
516
517 /* Gracefully exit ESC-sequence processing in case of misunderstanding */
518 void
519 bail_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
539 static void
540 get_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 */
550 void
551 vidc_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
665 static void
666 vidc_putchar(int c)
667 {
668 #ifdef TERM_EMU
669     vidc_term_emu(c);
670 #else
671     vidc_rawputchar(c);
672 #endif
673 }
674
675 static int
676 vidc_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
694 static int
695 vidc_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
716 static int
717 probe_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 */
739 static void
740 delay7(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  */
760 static void
761 delay1ms(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  */
776 static int
777 probe_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 */