Merge from vendor branch GCC:
[dragonfly.git] / sys / i386 / 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  * $DragonFly: src/sys/i386/boot/biosboot/Attic/probe_keyboard.c,v 1.2 2003/06/17 04:28:34 dillon Exp $
28  */
29
30 #include <sys/types.h>
31
32 #include <machine/cpufunc.h>
33
34 #include <i386/isa/isa.h>
35
36 #include <dev/kbd/atkbdcreg.h>
37
38 #include "boot.h"
39
40 #define PROBE_MAXRETRY  5
41 #define PROBE_MAXWAIT   400
42
43 #define IO_DUMMY        0x84
44
45 /* 7 microsec delay necessary for some keyboard controllers */
46 static void
47 delay7(void)
48 {
49     /* 
50      * I know this is broken, but no timer is avaiable yet at this stage...
51      * See also comments in `delay1ms()' in `io.c'.
52      */
53     inb(IO_DUMMY); inb(IO_DUMMY);
54     inb(IO_DUMMY); inb(IO_DUMMY);
55     inb(IO_DUMMY); inb(IO_DUMMY);
56 }
57
58 /* 
59  * Perform a simple test on the keyboard; issue the ECHO command and see
60  * if the right answer is returned. We don't do anything as drastic as
61  * full keyboard reset; it will be too troublesome and take too much time.
62  */
63 int
64 probe_keyboard(void)
65 {
66     int retry = PROBE_MAXRETRY;
67     int wait;
68     int i;
69
70     while (--retry >= 0) {
71         /* flush any noise */
72         while (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL) {
73             delay7();
74             inb(IO_KBD + KBD_DATA_PORT);
75             delay1ms();
76         }
77
78         /* wait until the controller can accept a command */
79         for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
80             if (((i = inb(IO_KBD + KBD_STATUS_PORT)) 
81                 & (KBDS_INPUT_BUFFER_FULL | KBDS_ANY_BUFFER_FULL)) == 0)
82                 break;
83             if (i & KBDS_ANY_BUFFER_FULL) {
84                 delay7();
85                 inb(IO_KBD + KBD_DATA_PORT);
86             }
87             delay1ms();
88         }
89         if (wait <= 0)
90             continue;
91
92         /* send the ECHO command */
93         outb(IO_KBD + KBD_DATA_PORT, KBDC_ECHO);
94
95         /* wait for a response */
96         for (wait = PROBE_MAXWAIT; wait > 0; --wait) {
97              if (inb(IO_KBD + KBD_STATUS_PORT) & KBDS_ANY_BUFFER_FULL)
98                  break;
99              delay1ms();
100         }
101         if (wait <= 0)
102             continue;
103
104         delay7();
105         i = inb(IO_KBD + KBD_DATA_PORT);
106 #ifdef PROBE_KBD_BEBUG
107         printf("probe_keyboard: got 0x%x.\n", i);
108 #endif
109         if (i == KBD_ECHO) {
110             /* got the right answer */
111             return (0);
112         }
113     }
114
115     return (1);
116 }