aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/clock.c4
-rw-r--r--src/floppy.c4
-rw-r--r--src/kbd.c55
-rw-r--r--src/util.h6
4 files changed, 44 insertions, 25 deletions
diff --git a/src/clock.c b/src/clock.c
index 9009d49..ee2d05f 100644
--- a/src/clock.c
+++ b/src/clock.c
@@ -488,10 +488,8 @@ handle_1586(struct bregs *regs)
set_code_fail(regs, RET_ECLOCKINUSE);
return;
}
- irq_enable();
while (!statusflag)
- cpu_relax();
- irq_disable();
+ wait_irq();
set_success(regs);
}
diff --git a/src/floppy.c b/src/floppy.c
index 922a2f5..ad7aa7f 100644
--- a/src/floppy.c
+++ b/src/floppy.c
@@ -176,7 +176,6 @@ floppy_reset_controller()
static int
wait_floppy_irq()
{
- irq_enable();
u8 v;
for (;;) {
if (!GET_BDA(floppy_motor_counter)) {
@@ -186,9 +185,8 @@ wait_floppy_irq()
v = GET_BDA(floppy_recalibration_status);
if (v & FRS_TIMEOUT)
break;
- cpu_relax();
+ wait_irq();
}
- irq_disable();
v &= ~FRS_TIMEOUT;
SET_BDA(floppy_recalibration_status, v);
diff --git a/src/kbd.c b/src/kbd.c
index 3714d33..650f1d4 100644
--- a/src/kbd.c
+++ b/src/kbd.c
@@ -23,6 +23,7 @@
#define KF1_LCTRL (1<<0)
#define KF1_LALT (1<<1)
+#define KF1_PAUSEACTIVE (1<<3)
#define KF1_SCROLL (1<<4)
#define KF1_NUM (1<<5)
#define KF1_CAPS (1<<6)
@@ -160,7 +161,7 @@ dequeue_key(struct bregs *regs, int incr, int extended)
regs->flags |= F_ZF;
return;
}
- cpu_relax();
+ wait_irq();
}
u8 ascii_code = GET_FARVAR(SEG_BDA, *(u8*)(buffer_head+0));
@@ -233,7 +234,9 @@ static void
handle_160a(struct bregs *regs)
{
u8 param[2];
+ irq_enable();
int ret = kbd_command(ATKBD_CMD_GETID, param);
+ irq_disable();
if (ret) {
regs->bx = 0;
return;
@@ -303,7 +306,9 @@ set_leds()
if (shift_flags == led_flags)
return;
+ irq_enable();
int ret = kbd_command(ATKBD_CMD_SETLEDS, &shift_flags);
+ irq_disable();
if (ret)
// Error
return;
@@ -319,8 +324,7 @@ handle_16(struct bregs *regs)
if (! CONFIG_KEYBOARD)
return;
- irq_enable();
-
+ // XXX - set_leds should be called from irq handler
set_leds();
switch (regs->ah) {
@@ -443,10 +447,10 @@ static struct scaninfo {
};
// Handle a scancode read from the ps2 port. Note that "noinline" is
-// used to make sure the call to call16_simpint in handle_09 doesn't
+// used to make sure the call to call16_simpint in process_key doesn't
// have the overhead of this function's stack.
static void noinline
-process_key(u8 scancode)
+__process_key(u8 scancode)
{
u8 flags0 = GET_BDA(kbd_flag0);
u8 flags1 = GET_BDA(kbd_flag1);
@@ -457,15 +461,22 @@ process_key(u8 scancode)
if ((scancode & ~0x80) == 0x1d)
// Second key of sequence
return;
- // Third key of sequence
+ // Third key of sequence - clear flag.
+ flags2 &= ~KF2_LAST_E1;
+ SET_BDA(kbd_flag2, flags2);
+
if (scancode == 0xc5) {
+ // Final key in sequence.
+
// XXX - do actual pause.
}
- flags2 &= ~KF2_LAST_E1;
- SET_BDA(kbd_flag2, flags2);
return;
}
+ // XXX - PrtScr should cause int 0x05
+ // XXX - Ctrl+Break should cause int 0x1B
+ // XXX - SysReq should cause int 0x15/0x85
+
switch (scancode) {
case 0x00:
dprintf(1, "KBD: int09 handler: AL=0\n");
@@ -611,6 +622,21 @@ process_key(u8 scancode)
SET_BDA(kbd_flag2, flags2);
}
+static void
+process_key(u8 key)
+{
+ if (CONFIG_KBD_CALL_INT15_4F) {
+ // allow for keyboard intercept
+ u32 eax = (0x4f << 8) | key;
+ u32 flags;
+ call16_simpint(0x15, &eax, &flags);
+ if (!(flags & F_CF))
+ return;
+ key = eax;
+ }
+ __process_key(key);
+}
+
// INT09h : Keyboard Hardware Service Entry Point
void VISIBLE16
handle_09()
@@ -625,18 +651,9 @@ handle_09()
dprintf(1, "keyboard irq but no keyboard data.\n");
goto done;
}
- u8 key = inb(PORT_PS2_DATA);
+ v = inb(PORT_PS2_DATA);
- if (CONFIG_KBD_CALL_INT15_4F) {
- // allow for keyboard intercept
- u32 eax = (0x4f << 8) | key;
- u32 flags;
- call16_simpint(0x15, &eax, &flags);
- if (!(flags & F_CF))
- goto done;
- key = eax;
- }
- process_key(key);
+ process_key(v);
done:
eoi_pic1();
diff --git a/src/util.h b/src/util.h
index c18fbba..7601b48 100644
--- a/src/util.h
+++ b/src/util.h
@@ -36,6 +36,12 @@ static inline void cpu_relax(void)
asm volatile("rep ; nop": : :"memory");
}
+// Atomically enable irqs and sleep until an irq; then re-disable irqs.
+static inline void wait_irq(void)
+{
+ asm volatile("sti ; hlt ; cli ; cld": : :"memory");
+}
+
static inline void nop(void)
{
asm volatile("nop");