ID:IA QEMM-386 and Keyboard Behaviour
Quarterdeck Technical Note #221
by: Michael Bolton
Release date: December 17, 1991
Last revised: July 10, 1992
QEMM-386 AND KEYBOARD BEHAVIOUR
Users sometimes experience "sticky shift keys" under QEMM -- the symptom is
that the Shift, Control, or NumLock keys appear to take effect even though
they have not been pressed. The IA parameter to QEMM can sometimes fix this
problem. To use it, simply add IA to the end of the QEMM line in CONFIG.SYS
If this does not work, QEMM can provide no other solution to the problem.
When IA is used, QEMM does not affect keyboard activity.
THE REAL CAUSE
The probable source of the difficulty is a program that intercepts or
redirects Interrupt 9, which is responsible for detecting keyboard activity.
TSRs often do this, especially those which pop up under the control of a hot
key, or those which monitor or accelerate keyboard performance. Application
programs can occasionally exhibit this behaviour as well. Such a program
reads the keyboard, and then decides whether the key is important to its
operation: if it is, the program interprets the key and performs one of its
own functions; if not, the program passes the keyboard event to the previous
owner of INT 9. Note that several programs may be attempting to monitor the
keyboard this way, and that several programs may be inspecting the keystroke
before it eventually reaches the system ROM BIOS, which is the original
handler of INT 9.
Before the appearance of the PC-AT architecture, the procedure to read the
1) inspect the keyboard port
2) reset the keyboard
After the reset, another key can be put into the keyboard port.
On the PC-AT and later machines (i.e. since 1985), the correct method is:
1) disable the keyboard;
2) read the keyboard port (this would allow a new key to be put into the
keyboard port if the keyboard had not been disabled by the first step);
3) reset the keyboard (which actually does not have any particular function
in this newer way of doing things);
4) re-enable the keyboard (which allows a new key to be put into the port).
To further complicate matters, machines that have a PS/2-style mouse must
disable that as well, but it is dangerous to do so if the mouse port does not
In fact, programs should be using another method (INT 15, Function 4F) to read
the keyboard -- which avoids all of these problems entirely.
Many programs apparently do not implement the later, correct methods of
reading the keyboard. Consequently, the old-style read-and-reset method
allows a new key to come in, perhaps before the program has had a chance to
pass the first key to the previous interrupt handler. By the time a decision
has been made to pass the key along, a different key may be in the keyboard
Keyboards do pace the keys they put in the keyboard port, and so if not too
much time elapses between reads of the port, the correct key will be passed.
Several things can affect this:
1) If some I/O ports that are accessed during this period are trapped by
QEMM, then that slows down the sequence of code, increasing the
likelihood that a new key may be in the keyboard port when it is read by
the next program down the chain.
Programs which read the keyboard read I/O port 64 as part of the process.
Port 64 controls the state of the the A20 address line, which must be
enabled for access to extended memory. When the A20 bit is enabled,
programs may also read and write to extended memory addresses instead of
wrapping to the bottom of conventional memory addresses. By default,
QEMM traps port 64 to detect programs which are attempting to manipulate
the state of the A20 line, which unfortunately shares its I/O port with
the keyboard controller. (The logic underlying the decision to place such
a crucial piece of system control hardware on the keyboard controller is
lost in the mists of time. All that is known is that there was a spare
bit in one of the registers on the keyboard controller, and a need for a
place to put the bit that would enable and disable the A20 line.) The
IGNOREA20 (IA) parameter instructs QEMM to refrain from trapping this I/O
port, and thus causes QEMM to ignore the keyboard completely. Note that
on Micro Channel machines, QEMM does not monitor port 64; it monitors
port 92 instead (since the latter, rather than the former, is used to
control the state of the A20 line on Micro Channel machines), and
therefore IA will have no effect on Micro Channel IBM PS/2s or other MCA
2) QEMM puts the processor into Virtual 86 mode when QEMM is in an ON state -
- essentially when expanded memory or High RAM is being provided. The
same is true of any 386 expanded memory manager --whether QEMM, DOS 5's
EMM386, Compaq's CEMMP, or the like; Virtual 8086 mode is necessary to
provide expanded memory or High RAM. In V86 mode, many instructions take
longer than in real mode, and interrupts themselves are slowed down,
again increasing the possibility that a keyboard event might be missed.
In this case, your 386 memory manager contributes to the overhead of
processing interrupts, but it is not actually causing the problem.
3) The above two scenarios are not usually a problem with most keys, simply
because people do not type fast enough to have another key available when
the next TSR (or the BIOS) tries to read a key. But on the newer 101-key
keyboards -- which first appeared in 1987, and which have separate number
and cursor keypads -- the cursor pad keys are special when NumLock is on.
A single Arrow key on the cursor pad with Numlock on generates six
keyboard interrupts on the downstroke and six more on the upstroke. They
1: "A New-Keyboard-style key will be the next key"
2: Left shift down
3: "A New Keyboard key coming next"
4: Arrow down
5: "A New Keyboard key coming next"
6: Left shift up
These come in rapid succession, controlled by the keyboard pace rate. If
there is a misbehaved keyboard interrupt handler in the chain, one of
these keyboard interrupts might get lost by the time it reaches the BIOS
handler. If the interrupt that is lost is the fake upshift, the BIOS will
think the shift key is still down.
The IA parameter to QEMM reduces the overhead on reads of port 64, and thus
might improve the situation such that the problem disappears --which will
alleviate situation (1) above. Removing QEMM will alleviate situation (2)
above, but this is not likely to be a particularly viable solution, since you
lose all of the benefits of 386 memory management --and therefore most of the
benefits of the 386 architecture. Note that other 386 memory managers will
probably cause your system to exhibit similar behaviour.
DESQview does hook the keyboard interrupt, but it uses the proper technique to
do so. QEMM does not hook the keyboard interrupt, and has only an incidental
effect on the keyboard as discussed above -- QEMM adds a small amount of
overhead to the system generally, and therefore can appear to be the "cause"
of the problem. However, neither QEMM nor DESQview, in and of themselves,
will cause sticky shift keys; the direct cause of invisibly held-down shift
keys is determined by some other aspect of your system.
IDENTIFYING THE CAUSE
Manifest can help you determine which program or programs are hooking INT 9.
Go into Manifest by typing MFT at the DOS prompt. Press F for First Meg, I
for Interrupts, and F3 for list by number. In the middle of the list, you
INT 09: Keyboard Event 0C43:7114 STINKKEY
What you see as the values displayed above will differ. The above address and
program are totally fictitious, and where the interrupt is pointing may be
affected by the STACKS settings in CONFIG.SYS. You should ensure that the
line STACKS=0,0 appears in CONFIG.SYS, so that device drivers which have
hooked INT 09 will display on this list. This will be necessaary if Manifest
is reporting that the owner of INT 09 is "DOS Stacks".
In the example above, INT 09 is being handled by a TSR called STINKKEY; it is
probably our culprit. Try removing the TSR (or device driver) that is hooking
INT 09, and see if that cures the problem. If not, continue removing TSRs or
device drivers that are hooking INT 09 until the offender is found. If the
problem happens from within an application, load Manifest as a TSR, and pop it
up from within the application that exhibits the problem. Note that the
application with the problem must be running in text mode (not graphics mode)
for Manifest to pop up.
FIXING THE PROBLEM
Temporary relief from sticky shift keys can sometimes be provided by tapping
the key that appears to be stuck. The BIOS will then see the proper state of
the shift key, and things should work normally. Keyboards have on-board
controllers which determine some of the behavior of the keyboard.
Specifically, the keyboard controller governs what scan code is generated by
each key, and how much time should elapse between keyboard interrupts when a
keystroke generates multiple interrupts. Therefore, different keyboards might
pace differently, and so exchanging the keyboard for another might affect the
problem -- and possibly improve things. Some BIOS setup programs contain an
option for "typematic" or "key repeat" or key delay rates; adjusting these may
alter the timing enough to provide some relief. One chipset that we are aware
of has a setup option for "Fast A20 Gate Enable"; toggling this setting has
helped some users, and similar options on other chipsets could help. Some
companies claim that BIOS upgrades can help alleviate sticky shift keys. All
of these are side issues, however. The actual problem is that a program in
keyboard interrupt chain -- probably the last one loaded -- is not reading the
keyboard properly. The simplest solution may be to remove the offending
program. If you require that program for a definite purpose, and if no other
well-behaved substitute can be found, consult the program's authors or
publishers for assistance.
*This technical note may be copied and distributed freely as long as it*
*is distributed in its entirety and it is not distributed for profit. *
* Copyright (C) 1991-2 by Quarterdeck Office Systems *
************************ E N D O F F I L E *************************