The comment above the yield() function suggests that yield()
allows interrupts for a short time. Currently this is only true
if seabios was built without CONFIG_THREADS or if yield() is
called from the main thread. Change the code to always call
check_irqs() in yield().
This fixes PS/2 keyboard initialization failures.
The code in src/hw/ps2port.c relies on yield() to briefly enable
interrupts. There is a comment above the yield() function in
__ps2_command(), where the author left a remark why the call to
yield() is actually needed.
Here is one of the call sequences leading to a PS/2 keyboard
initialization failure.
ps2_keyboard_setup()
|
ret = i8042_command(I8042_CMD_KBD_DISABLE, NULL);
# This command will register an interrupt if the PS/2 device
# controller raises interrupts for replies to a controller
# command.
|
ret = ps2_kbd_command(ATKBD_CMD_RESET_BAT, param);
|
ps2_command(0, command, param);
|
ret = __ps2_command(aux, command, param);
|
// Flush any interrupts already pending.
yield();
# yield() doesn't flush interrupts if the main thread
# hasn't reached wait_threads().
|
ret = ps2_sendbyte(aux, command, 1000);
# Reset the PS/2 keyboard controller and wait for
# PS2_RET_ACK.
|
ret = ps2_recvbyte(aux, 0, 4000);
|
for (;;) {
|
status = inb(PORT_PS2_STATUS);
# I8042_STR_OBF isn't set because the keyboard self
# test reply is still on wire.
|
yield();
# After a few yield()s the keyboard interrupt fires
# and clears the I8042_STR_OBF status bit. If the
# keyboard self test reply arrives before the
# interrupt fires the keyboard reply is lost and
# ps2_recvbyte() returns after the timeout.
}
Signed-off-by: Volker Rümelin <[email protected]>
---
src/stacks.c | 20 ++++++++++++++++++--
1 file changed, 18 insertions(+), 2 deletions(-)
diff --git a/src/stacks.c b/src/stacks.c
index 2fe1bfb..70e8283 100644
--- a/src/stacks.c
+++ b/src/stacks.c
@@ -623,9 +623,25 @@ yield(void)
return;
}
struct thread_info *cur = getCurThread();
- if (cur == &MainThread)
- // Permit irqs to fire
+ struct thread_info *mt = &MainThread;
+
+ // Permit irqs to fire
+ if (cur == mt) {
check_irqs();
+ } else {
+ asm volatile(
+ " pushl %%ebp\n" // backup %ebp
+ " movl %%esp, %%esi\n"
+ " movl (%%eax), %%esp\n" // switch to MainThread stack
+ " pushl %%esi\n" // backup current thread stack pointer
+ " calll %1\n" // check_irqs();
+ " popl %%esi\n"
+ " movl %%esi, %%esp\n" // switch back to current thread stack
+ " popl %%ebp\n" // restore %ebp
+ : "+a"(mt)
+ : "m"(check_irqs)
+ : "ebx", "ecx", "edx", "esi", "edi", "cc", "memory");
+ }
// Switch to the next thread
switch_next(cur);
--
2.26.2
_______________________________________________
SeaBIOS mailing list -- [email protected]
To unsubscribe send an email to [email protected]