summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Brown2006-12-05 10:45:39 +0100
committerMichael Brown2006-12-05 10:45:39 +0100
commit8bff0f06191a01a347db80d4c0bccb36f7cf847f (patch)
tree9237e4d1147421b4cba986191e7dfce778348c5a
parentTied NVO commands into the human-interactable settings code that I (diff)
downloadipxe-8bff0f06191a01a347db80d4c0bccb36f7cf847f.tar.gz
ipxe-8bff0f06191a01a347db80d4c0bccb36f7cf847f.tar.xz
ipxe-8bff0f06191a01a347db80d4c0bccb36f7cf847f.zip
Avoid draining the keyboard buffer during gateA20_set(). It shouldn't
technically be necessary, because the "enable A20" command requires only that the keyboard controller is ready to accept input (i.e. that its input buffer is empty), and shouldn't also require that the keyboard is ready to send output (i.e. that its output buffer is also empty). See http://www.smsc.com/main/tools/io-bios/42i.pdf section 3.1 ("Command Invocation") for a justification. gateA20_set() is called on every real-mode transition (in case some idiot piece of external code such as Intel's PXE stack decided it would be fun to re-disable A20), so draining the keyboard buffer means that we end up losing keypresses on some systems. In particular, this makes typing at the command line almost impossible, and causes Etherboot to ignore Ctrl-Alt-Del. We should really implement a gateA20_test() function to verify that gate A20 has been correctly enabled, and think about adding other commonly-used methods such as Fast Gate A20.
-rw-r--r--src/arch/i386/firmware/pcbios/gateA20.c18
1 files changed, 10 insertions, 8 deletions
diff --git a/src/arch/i386/firmware/pcbios/gateA20.c b/src/arch/i386/firmware/pcbios/gateA20.c
index 5a27e7069..cdc866850 100644
--- a/src/arch/i386/firmware/pcbios/gateA20.c
+++ b/src/arch/i386/firmware/pcbios/gateA20.c
@@ -27,16 +27,17 @@ enum { Disable_A20 = 0x2400, Enable_A20 = 0x2401, Query_A20_Status = 0x2402,
#define CF ( 1 << 0 )
#ifndef IBM_L40
-static void empty_8042 ( void )
-{
+static void empty_8042 ( void ) {
unsigned long time;
- char st;
time = currticks() + TICKS_PER_SEC; /* max wait of 1 second */
- while ((((st = inb(K_CMD)) & K_OBUF_FUL) ||
- (st & K_IBUF_FUL)) &&
- currticks() < time)
- inb(K_RDWR);
+ while ( ( inb ( K_CMD ) & K_IBUF_FUL ) &&
+ currticks() < time ) {
+ /* Do nothing. In particular, do *not* read from
+ * K_RDWR, because that will drain the keyboard buffer
+ * and lose keypresses.
+ */
+ }
}
#endif /* IBM_L40 */
@@ -66,6 +67,7 @@ void gateA20_set ( void ) {
: "=r" ( flags ), "=a" ( discard_a )
: "a" ( Enable_A20 ) );
+
if ( flags & CF ) {
/* INT 15 method failed, try alternatives */
#ifdef IBM_L40
@@ -78,7 +80,7 @@ void gateA20_set ( void ) {
empty_8042();
#endif /* IBM_L40 */
}
-
+
reentry_guard = 0;
}