Re: Patch?: linux-2.5.33/drivers/input/keyboard/atkbd.c allow SETLEDS to fail

From: Adam J. Richter (adam@yggdrasil.com)
Date: Tue Sep 10 2002 - 11:05:20 EST


On Mon, Sep 09, 2002 at 05:20:04PM +0200, Vojtech Pavlik wrote:
> There are not. If SETLEDS fails, then there is the GETID command, which
> is also allowed to fail (fails on AT (non-PS/2) keyboards, which are
> still common), and it most likely also fails on your keyboard. That's
> all.
>
> If you kill the SETLEDS command, then even without a keyboard, the
> keyboard will be detected, and sent commands, which will have to time
> out every time.

        100 milliseconds, which normally only happens when the user
hits CapsLock, NumLock or ScrollLock, which generally implies that a
keyboard is present. I suspect that you could change it to use mdelay
instead of udelay, so that other processes could do useful work during
the wait, which might be relevant even with a keyboard plugged in that
just happens to be slow if one is running a screen saver that cycles
the keyboard LED's. If it's important, you could also set a flag
when SETLEDS fails and not attempt further SETLEDS until another
sign of life from the keyboard is received (which would also address
the case of someone unplugging the keyboard after initialization).

        I also noticed a problem with plugging in a PS/2 keyboard
after initialization where it would not work, at least when I also had
the USB-to-PS/2 emulation enabled (if I booted with PS/2 keyboard
plugged in, both the USB and the PS/2 keyboards would work). I have
not checked the purely non-USB case for whether your code works for
loading the module without the keyboard present and then plugging the
keyboard in later.

        Without the USB-to-PS/2 emulation on my VD133 motherboard, I
can't type into lilo. Perhaps newer BIOSes have USB keyboard input
without need for hardware emulation, but I imagine that there are
quite a few computers with this problem. That would be OK if there
were some way for Linux to turn off USB-to-PS/2 keyboard emulation
once the Linux USB code is loaded. Currently, I get an infinite loop
of carriage returns when I do "modprobe hid" if I am using USB-to-PS/2
keyboard emulation.

        I agree that USB-to-PS/2 seems to be an ugly kludge, but I
think that the small cost due to orphaning certain oddball hardware
combinations is greater than the even smaller benefit of faster
SETLEDs (which I think could be achieved in other ways).

        The rest of this email is just about the PCI interrupt routing.

> > >I assume you have an USB keyboard, and the BIOS emulates a PS/2 keyboard
> > >for non-USB capable OSes.
> >
> > >Well, fix Linux irq router code, instead of damaging the keyboard code.
> >
> > How is the Linux IRQ routing code broken? As far as I know,
> > it only reads the information given to it and cannot reprogram the
> > hardware.
>
> It can.

        Thanks for the pointers to arch/i386/pci/irq.c and
drivers/pci/quirks.c. This code programs interrupt routing in a few
special cases and arch/i386/pci/irq.c has somewhat general underlying
facilities that could be put to more general use, but I do not see any
existing programming interface by which a user level program could
somehow get the kernel to try, for example, to reprogram pci device
00:07.2 to IRQ 10.

> > My understanding is that the BIOS is responsible for setting
> > up the IRQ routes of each device and writing them into each device's
> > PCI configuration register dword 15 byte 0 (INTERRUPT_LINE), which is
> > normally just 8 bits of RAM.
>
> Yes, but because the BIOS often writes nonsense to these config
> registers, Linux knows several southbridges and can fix the routing by
> hand.
>
> > The mechanism for *making* those routes
> > is vendor specific and handled by the BIOS at boot time. In the
> > particular case of my VD133, it apparently uses a Via VT82C598 PCI
> > bridge ("Apollo MVP3 AGP"), which I think is the component that would
> > have the secret bits for setting up routing from the main PCI bus to
> > the interrupt controllers.
>
> Most likely the interrupt routing is controlled by the southbridge (the
> ISA bridge device). See arch/i386/pci/irq.c. Maybe it's as easy as an
> entry for your southbridge is missing.
>
> > And those bits do appear to be secret.
>
> Not really. Most of them are actually documented. Namely for built-in
> devices like USB controllers, because those cannot be wired differently
> by different board manufacturers.

        There appears to be more black magic involved than is covered
by drivers/pci/quirks.c and arch/i386/pci/irq.c. Thanks for the
pointers. From the files that you mentioned and a lot of
experimentation of setpci and a minor kernel change, I have determined
that when I have my natsemi ethernet card plugged in, then, and *only
then*, I can get the USB controller to use the same IRQ as the
ethernet card, and, with the attached modification to
arch/i386/pci/irq.c, I can get the kernel to use that IRQ even though
there is no pirq entry for it. By the way, this isn't just the USB
controller being polled whenever an ethernet packet arrives. I've
verified that it works with the ethernet cable unplugged, as long as
the card is present. However, without the ethernet card installed,
the only way I have gotten the USB keyboard to work is with the
USB-to-PS/2 emulation. Right now, I have the ethernet card installed
and am composing this email on that USB keyboard via the Linux USB
drivers. Thanks again particularly for the pointer to
arch/i386/pci/irq.c.

        Here are the details of what I found, as the information may
be useful for other purposes in the future.

        pirq_via_{get,set} in arch/i386/pci/irq.c show a general
mechanism for assigning IRQ's though the Via south bridge chip.
dev_perq_info->irq[pin].link is an index into a table of 4 bit
nibbles starting at PCI configuration register 0x55 of the south
bridge. You write the IRQ that you want to route to into the
appropriate nibble. Here is an example from my system, with some
comments in brackets:

        setpci -v -s 00:07.0 55 56 57 58
        00:07.0:55 = c0 [ pirq#1 --> IRQ 12 ]
        00:07.0:56 = 0b [ pirq#2 --> IRQ 11 ]
        00:07.0:57 = 00
        00:07.0:58 = 00

        I can change the ethernet's IRQ routing from 11 to, say, 9,
and watch the ethernet immediately stop, by doing something like
"setpci -s 00:07.0 56=09".

        However, the built-in USB on the VT82C586B does not seem to use
this mechanism. There is no PIRQ entry for the pin that the USB controller
uses, and I cannot, for example, get the USB interrupts to show up on IRQ
ten by filling all of the southbridge configuration registers from 0x55
through 0x58 with 0xaa.

        It seems that the built-in USB on the VT82C586B has the same
feature as is described for the Via 686A/B in quirk_via_irqpic in
drivers/pci/quirks.c:

 * Via 686A/B: The PCI_INTERRUPT_LINE register for the on-chip
 * devices, USB0/1, AC97, MC97, and ACPI, has an unusual feature:
 * when written, it makes an internal connection to the PIC.

        This seems to work on my VD133 motherboard also, but it seems
only to work if I route it to the interrupt being used by the ethernet
card. It seems that there is some additional initialization needed
(and yes, I've checked that my choice of IRQ conforms that various IRQ
masks in arch/i386/pci/irq.c, and I've tried setting the south
bridge's configuration registers at 0x55 in conjunction with this.
So, it appears that there is some further interrupt routing
preparation that the kernel does not know about.

> Try the southbridge instead of the northbridge. I have several of the
> documents, and can send it to you if you tell me the right chip number.

        Great! Here is output of lspci on my system. I would be
interested in documents for any of the relevant chips. Although I've
kludged around the problem enough for my own use, I'd prefer to
develop a more general and correct fix for other VD133 users at least
and perhaps other boards if they have a similar BIOS problem.

00:00.0 Host bridge: VIA Technologies, Inc. VT82C691 [Apollo PRO] (rev 44)
00:01.0 PCI bridge: VIA Technologies, Inc. VT82C598 [Apollo MVP3 AGP]
00:07.0 ISA bridge: VIA Technologies, Inc. VT82C596 ISA [Apollo PRO] (rev 12)
00:07.1 IDE interface: VIA Technologies, Inc. VT82C586 IDE [Apollo] (rev 06)
00:07.2 USB Controller: VIA Technologies, Inc. VT82C586B USB (rev 08)
00:07.3 Host bridge: VIA Technologies, Inc.: Unknown device 3050 (rev 20)
00:10.0 Ethernet controller: National Semiconductor Corporation DP83815 10/100Mbps Ethernet with Wake on LAN
01:00.0 VGA compatible controller: ATI Technologies Inc 3D Rage Pro AGP AGP 1X/2X (rev 5c)

        Thanks for your help.

-- 
Adam J. Richter     __     ______________   575 Oroville Road
adam@yggdrasil.com     \ /                  Milpitas, California 95035
+1 408 309-6081         | g g d r a s i l   United States of America
                         "Free Software For The Rest Of Us."


- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/



This archive was generated by hypermail 2b29 : Sun Sep 15 2002 - 22:00:21 EST