]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/boot/a20.c
Merge branches 'tracing/ftrace', 'tracing/syscalls' and 'linus' into tracing/core
[linux-2.6-omap-h63xx.git] / arch / x86 / boot / a20.c
index 4063d630deff23cf2974e9839bc714de42b01f4c..7c19ce8c2442c219a1e85ee22798a8abaa0bdf2c 100644 (file)
@@ -2,6 +2,7 @@
  *
  *   Copyright (C) 1991, 1992 Linus Torvalds
  *   Copyright 2007-2008 rPath, Inc. - All Rights Reserved
+ *   Copyright 2009 Intel Corporation
  *
  *   This file is part of the Linux kernel, and is made available under
  *   the terms of the GNU General Public License version 2.
 #include "boot.h"
 
 #define MAX_8042_LOOPS 100000
+#define MAX_8042_FF    32
 
 static int empty_8042(void)
 {
        u8 status;
        int loops = MAX_8042_LOOPS;
+       int ffs   = MAX_8042_FF;
 
        while (loops--) {
                io_delay();
 
                status = inb(0x64);
+               if (status == 0xff) {
+                       /* FF is a plausible, but very unlikely status */
+                       if (!--ffs)
+                               return -1; /* Assume no KBC present */
+               }
                if (status & 1) {
                        /* Read and discard input data */
                        io_delay();
@@ -118,44 +126,37 @@ static void enable_a20_fast(void)
 
 int enable_a20(void)
 {
-#if defined(CONFIG_X86_ELAN)
-       /* Elan croaks if we try to touch the KBC */
-       enable_a20_fast();
-       while (!a20_test_long())
-               ;
-       return 0;
-#elif defined(CONFIG_X86_VOYAGER)
-       /* On Voyager, a20_test() is unsafe? */
-       enable_a20_kbc();
-       return 0;
-#else
        int loops = A20_ENABLE_LOOPS;
-       while (loops--) {
-               /* First, check to see if A20 is already enabled
-                  (legacy free, etc.) */
-               if (a20_test_short())
-                       return 0;
-
-               /* Next, try the BIOS (INT 0x15, AX=0x2401) */
-               enable_a20_bios();
-               if (a20_test_short())
-                       return 0;
-
-               /* Try enabling A20 through the keyboard controller */
-               empty_8042();
-               if (a20_test_short())
-                       return 0; /* BIOS worked, but with delayed reaction */
-
-               enable_a20_kbc();
-               if (a20_test_long())
-                       return 0;
-
-               /* Finally, try enabling the "fast A20 gate" */
-               enable_a20_fast();
-               if (a20_test_long())
-                       return 0;
-       }
-
-       return -1;
-#endif
+       int kbc_err;
+
+       while (loops--) {
+              /* First, check to see if A20 is already enabled
+                 (legacy free, etc.) */
+              if (a20_test_short())
+                      return 0;
+              
+              /* Next, try the BIOS (INT 0x15, AX=0x2401) */
+              enable_a20_bios();
+              if (a20_test_short())
+                      return 0;
+              
+              /* Try enabling A20 through the keyboard controller */
+              kbc_err = empty_8042();
+
+              if (a20_test_short())
+                      return 0; /* BIOS worked, but with delayed reaction */
+       
+              if (!kbc_err) {
+                      enable_a20_kbc();
+                      if (a20_test_long())
+                              return 0;
+              }
+              
+              /* Finally, try enabling the "fast A20 gate" */
+              enable_a20_fast();
+              if (a20_test_long())
+                      return 0;
+       }
+       
+       return -1;
 }