summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorsetje <none@none>2006-07-06 18:52:53 -0700
committersetje <none@none>2006-07-06 18:52:53 -0700
commit6ee4b8d7ef9a262e3f564e81b2b2f4d8e61ffe15 (patch)
tree5bc32d2bfb5e6451e4de94869ccde2ab49076c1d
parentfef1e07ef354c2dcda4dc397c33f5a5532432c7a (diff)
downloadillumos-gate-6ee4b8d7ef9a262e3f564e81b2b2f4d8e61ffe15.tar.gz
6412224 GRUB hangs when no i8042 is present
6412226 multiboot hangs when no i8042 is present Contributed by Juergen Keil <jk@tools.de>.
-rw-r--r--usr/src/grub/grub-0.95/stage2/asm.S33
-rw-r--r--usr/src/psm/stand/boot/i386/common/keyboard.c28
2 files changed, 51 insertions, 10 deletions
diff --git a/usr/src/grub/grub-0.95/stage2/asm.S b/usr/src/grub/grub-0.95/stage2/asm.S
index 5d4fe505ce..940313de24 100644
--- a/usr/src/grub/grub-0.95/stage2/asm.S
+++ b/usr/src/grub/grub-0.95/stage2/asm.S
@@ -1783,7 +1783,29 @@ ENTRY(gateA20)
jnz 3f
ret
-3: /* use keyboard controller */
+3: /*
+ * try to switch gateA20 using PORT92, the "Fast A20 and Init"
+ * register
+ */
+ mov $0x92, %dx
+ inb %dx, %al
+ /* skip the port92 code if it's unimplemented (read returns 0xff) */
+ cmpb $0xff, %al
+ jz 6f
+
+ /* set or clear bit1, the ALT_A20_GATE bit */
+ movb 4(%esp), %ah
+ testb %ah, %ah
+ jz 4f
+ orb $2, %al
+ jmp 5f
+4: and $0xfd, %al
+
+ /* clear the INIT_NOW bit; don't accidently reset the machine */
+5: and $0xfe, %al
+ outb %al, %dx
+
+6: /* use keyboard controller */
pushl %eax
call gloop1
@@ -1793,9 +1815,12 @@ ENTRY(gateA20)
gloopint1:
inb $K_STATUS
+ cmpb $0xff, %al
+ jz gloopint1_done
andb $K_IBUF_FUL, %al
jnz gloopint1
+gloopint1_done:
movb $KB_OUTPUT_MASK, %al
cmpb $0, 0x8(%esp)
jz gdoit
@@ -1816,6 +1841,8 @@ gdoit:
gloop1:
inb $K_STATUS
+ cmpb $0xff, %al
+ jz gloop2ret
andb $K_IBUF_FUL, %al
jnz gloop1
@@ -2123,6 +2150,10 @@ ENTRY(ascii_key_map)
ENTRY(console_getkey)
push %ebp
+wait_for_key:
+ call EXT_C(console_checkkey)
+ incl wait_for_key
+
call EXT_C(prot_to_real)
.code16
diff --git a/usr/src/psm/stand/boot/i386/common/keyboard.c b/usr/src/psm/stand/boot/i386/common/keyboard.c
index 095a46b432..dc3f09d68c 100644
--- a/usr/src/psm/stand/boot/i386/common/keyboard.c
+++ b/usr/src/psm/stand/boot/i386/common/keyboard.c
@@ -2,9 +2,8 @@
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
- * Common Development and Distribution License, Version 1.0 only
- * (the "License"). You may not use this file except in compliance
- * with the License.
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
@@ -20,7 +19,7 @@
* CDDL HEADER END
*/
/*
- * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
+ * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
@@ -182,8 +181,10 @@ kb_ischar(void)
return (1);
for (;;) {
- buffer_stat =
- inb(I8042_STAT) & (I8042_STAT_OUTBF | I8042_STAT_AUXBF);
+ buffer_stat = inb(I8042_STAT);
+ if (buffer_stat == 0xff)
+ return (0);
+ buffer_stat &= (I8042_STAT_OUTBF | I8042_STAT_AUXBF);
switch (buffer_stat) {
case 0:
@@ -456,7 +457,11 @@ kb_translate(unsigned char code)
void
kb_send(unsigned char cmd)
{
- while (inb(I8042_STAT) & I8042_STAT_INBF)
+ int retries;
+
+ for (retries = 0;
+ (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000;
+ retries++)
/* LOOP */;
outb(I8042_DATA, cmd);
}
@@ -487,6 +492,7 @@ void
kb_init(void)
{
unsigned char pic_mask;
+ int retries;
/*
* Write the command byte to turn off interrupts and
@@ -507,11 +513,15 @@ kb_init(void)
* 0x01: 0 = Disable aux interrupts.
*/
- while (inb(I8042_STAT) & I8042_STAT_INBF)
+ for (retries = 0;
+ (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000;
+ retries++)
/* LOOP */;
outb(I8042_CMD, I8042_WCB);
- while (inb(I8042_STAT) & I8042_STAT_INBF)
+ for (retries = 0;
+ (inb(I8042_STAT) & I8042_STAT_INBF) != 0 && retries < 100000;
+ retries++)
/* LOOP */;
outb(I8042_DATA, 0x64);