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