--- grub-0.97/stage2/asm.S.mactel-kbd	2006-06-12 17:00:10.000000000 -0400
+++ grub-0.97/stage2/asm.S	2006-06-12 17:03:38.000000000 -0400
@@ -1651,7 +1651,30 @@
 	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
@@ -1661,9 +1684,12 @@
 
 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
@@ -1684,6 +1710,8 @@
 
 gloop1:
 	inb	$K_STATUS
+	cmpb	$0xff, %al
+	jz	gloop2ret
 	andb	$K_IBUF_FUL, %al
 	jnz	gloop1
 
@@ -1994,8 +2022,25 @@
 	call	EXT_C(prot_to_real)
 	.code16
 
+.again:
+	mov	$0x11, %ah		/* poll kbd */
 	int	$0x16
 
+	jz	.again
+#if 0
+/* XXX handle serial here? -- pj */
+	jnz	.kbd
+#endif
+.kbd:
+	mov	$0x10, %ah
+	int	$0x16
+	cmp	$0xe0, %al
+	jnz	.not_ext
+	xor	%al, %al
+.not_ext:
+	and	%al, %al
+	jz	.func_key
+.func_key:
 	movw	%ax, %dx		/* real_to_prot uses %eax */
 	call	translate_keycode
 	call	remap_ascii_char
@@ -2003,7 +2048,7 @@
 	DATA32	call	EXT_C(real_to_prot)
 	.code32
 
-	movw	%dx, %ax
+	mov	%dx, %ax
 
 	pop	%ebp
 	ret
@@ -2029,7 +2074,7 @@
 	call	EXT_C(prot_to_real)	/* enter real mode */
 	.code16
 
-	movb	$0x1, %ah
+	movb	$0x11, %ah
 	int	$0x16
 
 	DATA32	jz	notpending
