ref: 7179a121a6c4426064818760e216c875fa78afcf
parent: 9140ae4a2ae59966c6d9b6e5cad9ecab6a0fda09
author: cinap_lenrek <[email protected]>
date: Fri Jan 20 15:03:38 EST 2012
9boot: always check if a20 is already enabled, use different keyboard code, retry on failure.
--- a/sys/src/boot/pc/a20.s
+++ b/sys/src/boot/pc/a20.s
@@ -2,69 +2,83 @@
#undef ORB
+TEXT a20test(SB), $0
+ LONG $1234567
+
+TEXT a20check(SB), $0
+ MOVL $10000, CX
+_loop:
+ LEAL a20test(SB), AX
+ MOVL (AX), BX
+ ADDL $12345, BX
+ MOVL BX, (AX)
+ ORL $(1<<20), AX
+ MOVL (AX), AX
+ CMPL AX, BX
+ JNZ _done
+ LOOP _loop
+ RET
+_done:
+ /* return directly to caller of a20() */
+ ADDL $4, SP
+ XORL AX, AX
+ RET
+
TEXT a20(SB), $0
+ CALL a20check(SB)
+
+ /* try bios */
CALL rmode16(SB)
STI
LWI(0x2401, rAX)
BIOSCALL(0x15)
- JC _biosfail
CALL16(pmode32(SB))
- RET
-_biosfail:
- CALL16(pmode32(SB))
+ CALL a20check(SB)
- /* fast a20 */
+ /* try fast a20 */
MOVL $0x92, DX
INB
- ANDB $0xFE, AX
- ORB $0x02, AX
+ TESTB $2, AL
+ JNZ _no92
+ ORB $2, AL
+ ANDB $0xfe, AL
OUTB
+_no92:
+ CALL a20check(SB)
- /* slow a20 */
- CALL a20wait(SB)
+ /* try keyboard */
+ CALL kbdempty(SB)
MOVL $0x64, DX
- MOVB $0xAD, AL
+ MOVB $0xd1, AL /* command write */
OUTB
-
- CALL a20wait(SB)
- MOVL $0x64, DX
- MOVB $0xD0, AL
- OUTB
-
- CALL a20wait2(SB)
+ CALL kbdempty(SB)
MOVL $0x60, DX
- INB
- PUSHL AX
-
- CALL a20wait(SB)
+ MOVB $0xdf, AL /* a20 on */
+ OUTB
+ CALL kbdempty(SB)
MOVL $0x64, DX
- MOVB $0xD1, AL
+ MOVB $0xff, AL /* magic */
OUTB
+ CALL kbdempty(SB)
- CALL a20wait(SB)
- MOVL $0x60, DX
- POPL AX
- ORB $2, AL
- OUTB
+ CALL a20check(SB)
- CALL a20wait(SB)
- MOVL $0x64, DX
- MOVB $0xAE, AL
- OUTB
+ /* fail */
+ XORL AX, AX
+ DECL AX
+ RET
-TEXT a20wait(SB), $0
-_a20wait:
+TEXT kbdempty(SB), $0
+_kbdwait:
MOVL $0x64, DX
INB
TESTB $1, AL
- JZ _a20wait2
- RET
-
-TEXT a20wait2(SB), $0
-_a20wait2:
- MOVL $0x64, DX
+ JZ _kbdempty
+ MOVL $0x60, DX
INB
+ JMP _kbdwait
+_kbdempty:
TESTB $2, AL
- JNZ _a20wait
+ JNZ _kbdwait
RET
--- a/sys/src/boot/pc/fns.h
+++ b/sys/src/boot/pc/fns.h
@@ -29,3 +29,11 @@
char *configure(void *f, char *path);
char *bootkern(void *f);
+/* a20.s */
+int a20(void);
+
+/* e820.s */
+ulong e820(ulong bx, void *p);
+
+/* apm.s */
+void apm(int id);
--- a/sys/src/boot/pc/sub.c
+++ b/sys/src/boot/pc/sub.c
@@ -283,8 +283,6 @@
*confend = 0;
}
-void apm(int id);
-
static void
apmconf(int id)
{
@@ -314,8 +312,6 @@
*confend = 0;
}
-ulong e820(ulong bx, void *p);
-
static void
e820conf(void)
{
@@ -380,8 +376,6 @@
return (p[0]<<24) | (p[1]<<16) | (p[2]<<8) | p[3];
}
-void a20(void);
-
char*
bootkern(void *f)
{
@@ -389,7 +383,8 @@
ulong n;
Exec ex;
- a20();
+ while(a20() < 0)
+ print("a20 enable failed\r\n");
if(readn(f, &ex, sizeof(ex)) != sizeof(ex))
return "bad header";