From ee2efa7303077ce98a745f637e213ba9a0965811 Mon Sep 17 00:00:00 2001 From: Kevin O'Connor Date: Sun, 20 Sep 2009 15:33:08 -0400 Subject: [PATCH] Support sleeping until an irq fires, and use where applicable. Add wait_irq() - it's more efficient than looping with cpu_relax(). Also, move kbd irq enables down - only kbd_command needs it. Also, make some minor code layout improvements to kbd.c. --- src/clock.c | 4 +--- src/floppy.c | 4 +--- src/kbd.c | 55 ++++++++++++++++++++++++++++++++++------------------ src/util.h | 6 ++++++ 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"); -- 2.25.1