delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/2000/10/10/08:22:35

Date: Tue, 10 Oct 2000 14:20:24 +0200 (IST)
From: Eli Zaretskii <eliz AT is DOT elta DOT co DOT il>
X-Sender: eliz AT is
To: Peter Remmers <Peter DOT Remmers AT t-online DOT de>
cc: djgpp AT delorie DOT com
Subject: Re: strange interrupt chaining problem with keyboard interrupt
In-Reply-To: <8rt7e2$ovq$18$1@news.t-online.com>
Message-ID: <Pine.SUN.3.91.1001010141631.12234C-100000@is>
MIME-Version: 1.0
Reply-To: djgpp AT delorie DOT com
Errors-To: nobody AT delorie DOT com
X-Mailing-List: djgpp AT delorie DOT com
X-Unsubscribes-To: listserv AT delorie DOT com

On Mon, 9 Oct 2000, Peter Remmers wrote:

> It also has a reentrance counter. If the reentrace counter is
> greater than zero it does NOT set up the stack again!
> And that's the problem: it expects an ACK from the keyboard, and
> it expects to be reentered by the ACK interrupt, and that means
> it expects SS and DS to have certain values when the interrupt
> occurs.

That sounds like a clear bug in KEYB.COM.  Given this information, I
cannot understand how does it work when some other TSR hooks the
keyboard interrupt ahead of KEYB.COM: the SS register is not
guaranteed to point to anything valid in an interrupt handler.

> Now, if I hook the keyboard interrupt and set up DJGPP's execution
> environment I (or the wrapper) overwrite keyb's SS and DS
> registers

This description is inaccurate, and I believe it led you to the wrong
conclusions.

When the protected-mode handler is entered, SS is not set to KEYB's
stack segment.  That's because KEYB.COM is a real-mode program, so the
value it loads into SS is some arbitrary number.  By contrast, the
interrupt handler set up by the wrapper is a protected-mode code, so
SS should have a valid selector in it.  The DPMI spec dictates that an
interrupt handler is entered with SS loaded with a selector which
points to a locked stack provided by the DPMI host.

So, by the time the wrapper is entered, the real-mode SS is long gone:
it is lost (or, rather, saved away by the DPMI host) in the process of
reflecting the hardware interrupt (which happened in real mode, as
part of KEYB's work) into protected mode.

Moreover, the DJGPP wrappers are non-reentrant, so they maintain a
reentrancy count and if the counter is non-zero, the wrapper does an
IRET without calling your handler.  So the interrupt from the ACK
doesn't even get into your C code.

> Solutions:
> - Make the *wrapper* call the next ISR after restoring DS and SS.
>   This is only possible with _go32_dpmi_chain_p_m_i_v(), or by
>   writing your own wrapper in assembly.

I think this is impossible at all, for the reasons I described above:
the DS and SS values seen by the wrapper are different from those
KEYB.COM wants to see.

> - install a real-mode callback for INT 0x15, which provides
>   a way to eat scancodes, to change them or leave them alone.

Yes, this will probably work, albeit with additional overhead of the
mode switch.

Another possible solution is to unhook the keyboard interrupt before
you lcall the previous handler, and then hook it again after the
called handler returns.  I don't know how safe it is to call DPMI
services inside a hardware interrupt handler, though.

As yet another possibility, you could try calling the real-mode ISR
directly from your handler, by using _go32_dpmi_simulate_fcall_iret.
(This would require to get the address of the RM handler during
initialization.)  That function and the underlying DPMI call allow you
to control the values that are loaded into the registers of the RM
handler when it is called, so perhaps you could save and restore the
values of SS and DS.  The downside is that the DJGPP SIGINT support
will not work, but I doubt if you want it in such a program, anyway.

- Raw text -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019