ref: a597496b19993379ad2cde4d7dd11e20b2122c00
parent: 3e9ae26c2ea9c1b0c1bfcc0ad02c58bc65cb5294
author: cinap_lenrek <[email protected]>
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;
}