code: plan9front

Download patch

ref: a597496b19993379ad2cde4d7dd11e20b2122c00
parent: 3e9ae26c2ea9c1b0c1bfcc0ad02c58bc65cb5294
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Sat Apr 6 12:35:37 EDT 2024

9boot: use BIOS tick counter instead of INT 0x15 WAIT

To implement keyboard input timeout, we used
to poll the keyboard in a loop with a 100ms
sleep in between using INT 0x15 WAIT BIOS call.

But it seems iPXE breaks the BIOS call, making
it just hang.

The BIOS has a 32-bit tick counter at
040:006C that has a period of 54.9254ms.

Using that instead of the WAIT call appears to be
more reliable and makes it work in iPXE.

Implementation note:

Because the counter has a wrap around value
at non-power-of-two, only check if the counter changed
and counting down the millisecond timeout when it did.

--- a/sys/src/boot/pc/fns.h
+++ b/sys/src/boot/pc/fns.h
@@ -10,7 +10,6 @@
 void start(void *sp);
 void cgaputc(int c);
 int kbdgetc(void);
-void usleep(int t);
 void halt(void);
 void jump(void *pc);
 
--- a/sys/src/boot/pc/l.s
+++ b/sys/src/boot/pc/l.s
@@ -145,17 +145,6 @@
 	ANDL $0xFFFF, AX
 	RET
 
-TEXT usleep(SB), $0
-	MOVL t+4(SP), AX
-	PUSHL AX
-	CALL rmode16(SB)
-	STI
-	POPR(rDX)
-	POPR(rCX)
-	MOVB $0x86, AH
-	BIOSCALL(0x15)
-	JMP _pret32
-
 #ifdef PXE
 
 TEXT pxeinit(SB), $0
--- a/sys/src/boot/pc/sub.c
+++ b/sys/src/boot/pc/sub.c
@@ -165,11 +165,18 @@
 static int
 timeout(int ms)
 {
+	long v;
+	volatile long *ticks = (long *) 0x46c;
+
+	v = *ticks;
 	while(ms > 0){
 		if(getc() != 0)
 			return 1;
-		usleep(100000);
-		ms -= 100;
+
+		if (v != *ticks) {
+			ms -= 55;
+			v = *ticks;
+		}
 	}
 	return 0;
 }