Date: Tue, 10 Oct 2000 14:20:24 +0200 (IST) From: Eli Zaretskii X-Sender: eliz AT is To: Peter Remmers 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: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII 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 Precedence: bulk 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.