Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 16 Aug 2001 23:03:43 +0900
From:      Kazutaka YOKOTA <yokota@zodiac.mech.utsunomiya-u.ac.jp>
To:        current@freebsd.org
Cc:        yokota@zodiac.mech.utsunomiya-u.ac.jp
Subject:   keyboard reset (was: Re: FreeBSD's aggressive keyboard probe/attach)
Message-ID:  <200108161403.XAA10653@zodiac.mech.utsunomiya-u.ac.jp>

next in thread | raw e-mail | index | archive | help
I am entering a tricky part now :-)

----------- Keyboard reset

Because there are so many complicated issues here, I will start with
describing something I know about what BIOS and FreeBSD keyboard
driver do. (Beware, this is a long message.)


1. What BIOS does

During AT BIOS POST, things happen as follows.

Step 1. It sends the reset command to the keyboard.
Step 2. It waits for the result code.  During this reset operation
        the embedded controller inside the keyboard will flash LEDs(*1).
Step 3. If it doesn't receive the result code, it assumes
        there is no keyboard. Depending on your BIOS (and BIOS setup),
        you will get the error message "keyboard not present."
Step 4. If it has received the result code, but it signifies an error,
        you will get an error message too.
Step 5. If it has received the result code, and there was no error,
        the BIOS sends the send-ID command to the keyboard.
Step 6. If the keyboard is 101/102 enhanced keyboard (or newer), it will
        respond with a 2 byte ID code(*2). The original AT 84 keyboard
        (and some old notebook computers too) doesn't support this
        command and will report error.
Step 7. If the BIOS recognizes this ID code(*2), it will set the bit 4
        in the keyboard status byte in the BIOS data area (0x496).
Step 8. The BIOS then send the set-LED command. This is typically done
        to turn the NumLock LED on.
Step 9. The BIOS optionally send set-repeat-rate command to set repeat
        delay and rate which you have specified in the BIOS setup menu.
        (The original IBM AT didn't have such menu, thus, didn't send
        this command.)

Note *1: we can certainly see the LEDs flash. But, this is not caused
         by the set-LED command from the host computer. It is by
         the keyboard's internal routine. In addition, LED flash is 
         not detectable from outside, in an electrical way by 
         the host computer or KVM.  There is no signal line in 
         the keyboard cable associated with the LEDs!
         We should also remember there are some keyboard which doesn't
         have LEDs.
Note *2: a typical ID code is 0x41ab for the US 101 keyboard. But
         other keyboards may send a different code. If the ID code
         is not one of those the BIOS knows about, the bit 4 at 0x496
         won't be set.

If the machine is in warm-boot sequence, the entire above keyboard probe
may be skipped. 

It is also important to note that there is no BIOS service or status
byte (or bit) in BIOS data area which tells us the presence or absence
of the keyboard.  As already pointed out in this mailing list by many
people, we cannot rely on the bit 4 at the BIOS data area 0x496 for
this purpose; this bit is set only when the keyboard identifies it
self as one of enhanced type (12 function keys and separate cursor pad
keys) AND the BIOS recognizes its ID code.


2. What FreeBSD atkbd driver does

Step 1. the probe routine sends the echo command to the keyboard port.
        If a keyboard is present behind the keyboard port, it will respond.
Step 2. If there was no response, the driver assumes that there is no
        keyboard and note as such. The driver will fail to install
        ONLY IF you set bit 0 (FAIL_IF_NO_KBD) in the flags for atkbd.
Step 3. If the keyboard is present, then the attach routine first try
        to retrieve the ID code from the keyboard by issuing 
        the send-ID command. (The returned ID code will be saved.)
Step 4. Then the reset command is sent(*1), in order to put the keyboard
        in known state(*1). (If the keyboard returns error and the
        FAIL_IF_NO_KBD bit is set in the device flags, the atkbd will 
        fail to install.)
Step 5. The set-LED command is sent. It typically set the NumLock LED
        which was turned off reset in the step 4.
Step 6. The set-repeat-rate command is sent.

Note *1: if you really don't want to reset the keyboard, you may set
         the NO_RESET flags to skip it.
Note *2: if you warm boot the machine after you used it under another
         OS, we need to reset the keyboard to put it in known state,
         in case the BIOS doesn't do so for us.  It is true that there is
         not much room for the other OSes to configure the keyboard 
         in arcane state/mode, but I have seen in some Linux mailing 
         list that someone suggested that they should use the scan
         code set 3. The atkbd driver uses the scan code set 2 
         (this is the default after reset), or the set 1 for old
         ThinkPad keyboards (you need to set the ALT_SCANCODESET in 
         the atkbd device flags for this).

Note: all these FAIL_IF_NO_KBD, NO_RESET, and ALT_ACANCODESET flags are
      documented in the man page for atkbd(4).


3. Difference between the BIOS POST and atkbd

Except that the atkbd driver uses the echo command first and that the
order of the send-ID and reset commands is different, both do
essentially the same thing.


4. So, what the problem with the atkbd driver?

I am not convinced that the atkbd driver's behavior is too aggressive.
If you say it is, what the BIOS does must also be regarded as too
aggressive.

I must say that if the atkbd's probe/attach causes the KVM problems
because ScrollLock LED is flashed, then, BIOS POST must cause the same
problem too.  Remember that during both BIOS POST and atkbd
probe/attach, LEDs are flashed because of the INTERNAL reset/test
routine in the keyboard during the reset command; it is not caused by
the set-LED command from the host computer.

(Well, if the ScrollLock bit in the BIOS data area was set when the
machine first starts, the set-LED command will turn the ScrollLock LED
on. But, this is usually not the case.)

If you think that the reset command in the atkbd driver is harmful,
set NO_RESET in the atkbd driver flags and see if it makes difference.

I suspect that what Belkin fixed in their firmware v1.9 was not
something about LEDs, but either of the followings:

a) Pass any commands from the host computer to the keyboard even
   if the keyboard is not directed to this computer.

Or,

b) Process/emulate the reset, echo, send-ID, set-LED, and set-repeat-rate
   commands (and possibly other keyboard commands) internally in KVM,
   so that the host computer is made to think a real keyboard is directly
   connected.

As the BIOS POST does essentially the same things as the atkbd driver
except for the echo command, my guess is that the reset, send-ID,
send-LED and set-repeat-rate commands were already emulated in v1.6
(otherwise you get the "keyboard not present" error during BIOS POST),
and the support for the echo command was added in v.1.9. I find it is
good for them to make emulation better than before. If they want their
KVM to be as transparent as possible both to host computers and to the
keyboard, their emulation had better be good and complete.


5. Note on atbkd driver flags FAIL_IF_NO_KBD (0x1)

This flag is optional. If it is not set, the atkbd driver DOES install
itself even if the AT keyboard is not present, by default. This has
been the behavior since our days as far back as FreeBSD 1.X.

This flag is currently set in /boot/device.hint. It was added in
order to support systems with the USB keyboard only.  Because if the
atkbd installs when the AT keyboard is not there, syscons will grab it
before the USB keyboard becomes accessible. 

This flag, convinced with the flags 0x100 (AUTO_DETECT_KBD, it's also
default in /boot/device.hints now) for syscons, makes syscons search
for a keyboard periodically while it isn't using one, and as soon as a
USB keyboard becomes available, it will be used. If you attach the
second USB keyboard, you cannot use this one (instead of the first
one) until the first one is detached.  You can force syscons to use
the second USB keyboard via kbdconrol. But, it is not automatic.

We can improve our current behavior of syscons and keyboard drivers
in the following approaches.

a) Remove the FAIL_IF_NO_KBD flag from /boot/device.hints.
   Leave the AUTO_DETECT_KBD as it is now for syscons, so that
   syscons searches for a keyboard periodically while it isn't using
   one. Add a script to /etc/usbd.conf to switch to the USB keyboard.
   This way, the last USB keyboard attached will be the keyboard for
   syscons.  Even if the atkbd driver is present, you will be able to
   use the USB keyboard. But, you can use one keyboard only at one time. 
   (This was suggested by someone in the past. I don't remember who.)
   
b) Remove the FAIL_IF_NO_KBD flag from /boot/device.hints.
   Implement a general/virtual keyboard driver which will grab any
   keyboard devices in the system, combine all the input and forward
   it to syscons (as John Baldwin suggested recently).
   This way, we use all the keyboard attached to the system at once.

c) Remove the FAIL_IF_NO_KBD flag from /boot/device.hints.
   Leave the AUTO_DETECT_KBD as it is now for syscons, so that
   syscons searches for a keyboard periodically while it isn't using
   one. Make syscons not grab the atkbd driver while the real AT keyboard
   is not present. Do so only when it becomes available.
   This way if you plug the USB keyboard before you plug the AT
   keyboard, the USB keyboard will be used. But, once the AT
   keyboard is plugged while there is no USB keyboard, it will be 
   the keyboard for syscons and the USB keyboard will never be used,
   because we cannot detect the removal of the AT keyboard.
   (You can manually override this via kbdcontrol.)

I must admit that I have known these ideas for a long time but not
implemented any so far ;-<  

I always liked the idea b), but haven't designed it yet.

Probably the most reasonable thing to do is, in the short run, a).
But there still is a snag ;-(

Some USB keyboards have a PS/2 mouse connector and identify itself as
a USB keyboard AND a USB mouse. The current implementation of usbd(8)
doesn't handle this situation well; it find action for one device only,
not for both.  If this keyboard is detected as ukbd0 and ums0, usbd(8)
will execute action for either ukbd0 or ums0, for whichever device a
matching entry is found in /etc/usbd.conf first.

(The USB keyboard with USB HUB function seems not have this problem, as
it appears to identify itself as a HUB with a keyboard attached to it as
a child.)

c) is easy to implement. So, we can settle for c) until usbd(8) is
fixed and a) becomes feasible.

Kazu

To Unsubscribe: send mail to majordomo@FreeBSD.org
with "unsubscribe freebsd-current" in the body of the message




Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200108161403.XAA10653>