Initial import from FreeBSD RELENG_4:
[dragonfly.git] / sys / platform / pc32 / boot / biosboot / probe_keyboard.c
1 /*-
2  * Copyright (c) 1997 Kazutaka YOKOTA (yokota@zodiac.mech.utsunomiya-u.ac.jp)
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * $FreeBSD: src/sys/i386/boot/biosboot/probe_keyboard.c,v 1.15 1999/08/28 00:43:13 peter Exp $
27  */
28
29 #include <sys/types.h>
30
31 #include <machine/cpufunc.h>
32
33 #include <i386/isa/isa.h>
34
35 #include <dev/kbd/atkbdcreg.h>
36
37 #include "boot.h"
38
39 #define PROBE_MAXRETRY  5
40 #define PROBE_MAXWAIT   400
41
42 #define IO_DUMMY        0x84
43
44 /* 7 microsec delay necessary for some keyboard controllers */
45 static void
46 delay7(void)
47 {
48     /* 
49      * I know this is broken, but no timer is avaiable yet at this stage...
50      * See also comments in `delay1ms()' in `io.c'.
51      */
52     inb(IO_DUMMY); inb(IO_DUMMY);
53     inb(IO_DUMMY); inb(IO_DUMMY);
54     inb(IO_DUMMY); inb(IO_DUMMY);
55 }
56
57 /* 
58  * Perform a simple test on the keyboard; issue the ECHO command and see
59  * if the right answer is returned. We don't do anything as drastic as
60  * full keyboard reset; it will be too troublesome and take too much time.
61  */
62 int
63 probe_keyboard(void)
64 {
65     int retry = PROBE_MAXRETRY;
66     int wait;
67     int i;
68
69     while (--retry >= 0) {
70         /* flush any noise */
71         while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
72             delay7();
73             inb(IO_KBD + KBD_DATA_PORT);
74             delay1ms();
75         }
76
77         /* wait until the controller can accept a command */
78         for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
79             if (((i = inb(IO_KBD + KBD_STATUS_PORT)) 
80                 & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0)
81                 break;
82             if (i & KBDS_ANY_BUFFER_FULL) {
83                 delay7();
84                 inb(IO_KBD + KBD_DATA_PORT);
85             }
86             delay1ms();
87         }
88         if (wait <= 0)
89             continue;
90
91         /* send the ECHO command */
92         outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
93
94         /* wait for a response */
95         for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
96              if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)
97                  break;
98              delay1ms();
99         }
100         if (wait <= 0)
101             continue;
102
103         delay7();
104         i = inb(IO_KBD + KBD_DATA_PORT);
105 #ifdef PROBE_KBD_BEBUG
106         printf("probe_keyboard: got 0x%x.\n", i);
107 #endif
108         if (i == KBD_ECHO) {
109             /* got the right answer */
110             return (0);
111         }
112     }
113
114     return (1);
115 }