When enabling A20, put upper limit on amount of time we wait for the
authorYONETANI Tomokazu <y0netan1@dragonflybsd.org>
Sun, 22 Apr 2007 10:43:00 +0000 (10:43 +0000)
committerYONETANI Tomokazu <y0netan1@dragonflybsd.org>
Sun, 22 Apr 2007 10:43:00 +0000 (10:43 +0000)
keyboard controller to get ready (65K x ISA access time, visually
around 1 second).  If we have wait more than that amount it's likely
that the hardware is a legacy-free one and simply doesn't have keyboard
controller and doesn't require enabling A20 at all.

Taken-from: FreeBSD (with modifications suggested by Matt)

 relavant commit logs(and discussion):
  http://docs.FreeBSD.org/cgi/mid.cgi?200604110439.k3B4dTOD072774
  http://docs.FreeBSD.org/cgi/mid.cgi?200604112053.k3BKrnC1053262
  http://docs.FreeBSD.org/cgi/mid.cgi?200604260605.k3Q65GZZ095546

sys/boot/i386/cdboot/cdboot.S
sys/boot/i386/pxeldr/pxeldr.S
sys/dev/misc/atkbdc_layer/atkbdc_isa.c
sys/dev/misc/kbd/atkbd.c
sys/dev/misc/kbd/atkbdc.c

index 1a2ca1d..daa7963 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * $FreeBSD: src/sys/boot/i386/cdboot/cdboot.s,v 1.9 2001/11/07 01:20:33 jhb Exp $
- * $DragonFly: src/sys/boot/i386/cdboot/Attic/cdboot.S,v 1.7 2006/01/13 19:41:50 dillon Exp $
+ * $DragonFly: src/sys/boot/i386/cdboot/Attic/cdboot.S,v 1.8 2007/04/22 10:43:00 y0netan1 Exp $
  */
 
 /*
@@ -461,10 +461,17 @@ twiddle:  push %ax                        # Save
                ret
 
                /*
-                * Enable A20
+                * Enable A20. Put upper limit on amount of time we wait for the
+                * keyboard controller to get ready (65K x ISA access time). If
+                * we wait more than that amount it's likely that the hardware
+                * is legacy-free and simply doesn't have keyboard controller
+                * and don't need enabling A20 at all.
                 */
 seta20:        cli                             # Disable interrupts
-seta20.1:      in $0x64,%al                    # Get status
+               xor %cx,%cx                     # Clear
+seta20.1:      inc %cx                         # Increment, overflow?
+               jz seta20.3                     # Yes
+               in $0x64,%al                    # Get status
                test $0x2,%al                   # Busy?
                jnz seta20.1                    # Yes
                mov $0xd1,%al                   # Command: Write
@@ -474,7 +481,7 @@ seta20.2:   in $0x64,%al                    # Get status
                jnz seta20.2                    # Yes
                mov $0xdf,%al                   # Enable
                out %al,$0x60                   #  A20
-               sti                             # Enable interrupts
+seta20.3:      sti                             # Enable interrupts
                ret                             # To caller
 
                /*
index aac2632..0b565bf 100644 (file)
@@ -14,7 +14,7 @@
  *
  *
  * $FreeBSD: src/sys/boot/i386/pxeldr/pxeldr.s,v 1.9 2003/09/03 08:12:20 phk Exp $
- * $DragonFly: src/sys/boot/i386/pxeldr/Attic/pxeldr.S,v 1.4 2004/07/18 23:40:09 dillon Exp $
+ * $DragonFly: src/sys/boot/i386/pxeldr/Attic/pxeldr.S,v 1.5 2007/04/22 10:43:00 y0netan1 Exp $
  */
 
 /*
@@ -234,10 +234,17 @@ putc:             movw $0x7,%bx                   # attribute for output
                jmp putstr                      # keep looping
 
                /*
-                * Enable A20
+                * Enable A20. Put upper limit on amount of time we wait for the
+                * keyboard controller to get ready (65K x ISA access time). If
+                * we wait more than that amount it's likely that the hardware
+                * is legacy-free and simply doesn't have keyboard controller
+                * and don't need enabling A20 at all.
                 */
 seta20:        cli                             # Disable interrupts
-seta20.1:      inb $0x64,%al                   # Get status
+               xor %cx,%cx                     # Clear
+seta20.1:      inc %cx                         # Increment, overflow?
+               jz seta20.3                     # Yes
+               inb $0x64,%al                   # Get status
                testb $0x2,%al                  # Busy?
                jnz seta20.1                    # Yes
                movb $0xd1,%al                  # Command: Write
@@ -247,7 +254,7 @@ seta20.2:   inb $0x64,%al                   # Get status
                jnz seta20.2                    # Yes
                movb $0xdf,%al                  # Enable
                outb %al,$0x60                  #  A20
-               sti                             # Enable interrupts
+seta20.3:      sti                             # Enable interrupts
                retw                            # To caller
 
                /*
index cb0d52e..df76e8b 100644 (file)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/isa/atkbdc_isa.c,v 1.14.2.1 2000/03/31 12:52:05 yokota Exp $
- * $DragonFly: src/sys/dev/misc/atkbdc_layer/atkbdc_isa.c,v 1.7 2006/12/22 23:26:17 swildner Exp $
+ * $DragonFly: src/sys/dev/misc/atkbdc_layer/atkbdc_isa.c,v 1.8 2007/04/22 10:43:00 y0netan1 Exp $
  */
 
 #include "opt_kbd.h"
@@ -101,6 +101,11 @@ atkbdc_probe(device_t dev)
        struct resource *port1;
        int             error;
        int             rid;
+#if defined(__i386__)
+       bus_space_tag_t tag;
+       bus_space_handle_t ioh1;
+       volatile int    i;
+#endif
 
        /* check PnP IDs */
        if (ISA_PNP_PROBE(device_get_parent(dev), dev, atkbdc_ids) == ENXIO)
@@ -126,6 +131,28 @@ atkbdc_probe(device_t dev)
                return ENXIO;
        }
 
+#if defined(__i386__)
+       /*
+        * Check if we really have AT keyboard controller. Poll status
+        * register until we get "all clear" indication. If no such
+        * indication comes, it probably means that there is no AT
+        * keyboard controller present. Give up in such case. Check relies
+        * on the fact that reading from non-existing in/out port returns
+        * 0xff on i386. May or may not be true on other platforms.
+        */
+       tag = rman_get_bustag(port0);
+       ioh1 = rman_get_bushandle(port1);
+       for (i = 65536; i != 0; --i) {
+               if ((bus_space_read_1(tag, ioh1, 0) & 0x2) == 0)
+                       break;
+       }
+       if (i == 0) {
+               bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
+               bus_release_resource(dev, SYS_RES_IOPORT, 1, port1);
+               return ENXIO;
+       }
+#endif
+
        error = atkbdc_probe_unit(device_get_unit(dev), port0, port1);
 
        bus_release_resource(dev, SYS_RES_IOPORT, 0, port0);
index dbf6e7f..59de1f7 100644 (file)
@@ -24,7 +24,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/kbd/atkbd.c,v 1.25.2.4 2002/04/08 19:21:38 asmodai Exp $
- * $DragonFly: src/sys/dev/misc/kbd/atkbd.c,v 1.13 2006/12/22 23:26:17 swildner Exp $
+ * $DragonFly: src/sys/dev/misc/kbd/atkbd.c,v 1.14 2007/04/22 10:43:00 y0netan1 Exp $
  */
 
 #include "opt_kbd.h"
@@ -270,12 +270,12 @@ atkbd_configure(int flags)
        int arg[2];
        int i;
 
-       /* probe the keyboard controller */
-       atkbdc_configure();
-
-       /* if the driver is disabled, unregister the keyboard if any */
-       if ((resource_int_value("atkbd", ATKBD_DEFAULT, "disabled", &i) == 0)
-           && i != 0) {
+       /*
+        * Probe the keyboard controller, if not present or if the driver
+        * is disabled, unregister the keyboard if any.
+        */
+       if (atkbdc_configure() != 0 ||
+           resource_disabled("atkbd", ATKBD_DEFAULT)) {
                i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT);
                if (i >= 0) {
                        kbd = kbd_get_keyboard(i);
index 1854ce0..c3e579e 100644 (file)
@@ -28,7 +28,7 @@
  * SUCH DAMAGE.
  *
  * $FreeBSD: src/sys/dev/kbd/atkbdc.c,v 1.5.2.2 2002/03/31 11:02:02 murray Exp $
- * $DragonFly: src/sys/dev/misc/kbd/atkbdc.c,v 1.9 2007/01/15 00:11:36 dillon Exp $
+ * $DragonFly: src/sys/dev/misc/kbd/atkbdc.c,v 1.10 2007/04/22 10:43:00 y0netan1 Exp $
  * from kbdio.c,v 1.13 1998/09/25 11:55:46 yokota Exp
  */
 
@@ -143,6 +143,9 @@ atkbdc_configure(void)
        bus_space_handle_t h1;
        int port0;
        int port1;
+#if defined(__i386__)
+       volatile int i;
+#endif
 
        port0 = IO_KBD;
        resource_int_value("atkbdc", 0, "port", &port0);
@@ -163,6 +166,24 @@ atkbdc_configure(void)
        h0 = (bus_space_handle_t)port0;
        h1 = (bus_space_handle_t)port1;
 #endif
+
+#if defined(__i386__)
+       /*
+        * Check if we really have AT keyboard controller. Poll status
+        * register until we get "all clear" indication. If no such
+        * indication comes, it probably means that there is no AT
+        * keyboard controller present. Give up in such case. Check relies
+        * on the fact that reading from non-existing in/out port returns
+        * 0xff on i386. May or may not be true on other platforms.
+        */
+       for (i = 65536; i != 0; --i) {
+               if ((bus_space_read_1(tag, h1, 0) & 0x2) == 0)
+                       break;
+       }
+       if (i == 0)
+                return ENXIO;
+#endif
+
        return atkbdc_setup(atkbdc_softc[0], tag, h0, h1);
 }