Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 12 Sep 1999 00:02:53 +0200 (CEST)
From:      hmo@sep.hamburg.com (Helge Oldach)
To:        freebsd-doc@freebsd.org
Cc:        j@ida.interface-business.de
Subject:   12.4.3.2.3. Support for Cheap Multi-UART Cards
Message-ID:  <199909112202.AAA05385@sep.hamburg.com>

next in thread | raw e-mail | index | archive | help
Folks,

here is a chapter for The Handbook concerning cheap multi-UART cards.
Hope the chapter numbering is still right, please change ad lib.


12.4.3.2.3. Support for Cheap Multi-UART Cards

Ever wondered about FreeBSD support for your 20$ multi-I/O card with two
(ore more) COM ports, sharing IRQs? Here's how:

Usually the only option to support these kind of boards is to use a
distinct IRQ for each port. For example, if your CPU board has an
on-board COM1 port (aka sio0 - I/O address 0x3F8 and IRQ 4) and you have
an extension board with two UARTs, you'll commonly need to configure
them as COM2 (aka sio1 - I/O address 0x2F8 and IRQ 3), and the third
port (aka sio2) as I/O 0x3E8 and IRQ 5. Obviously this is a waste of IRQ
ressources, as it should be basically possible to run both extension
board ports using a single IRQ with the COM_MULTIPORT configuration
described in the previous sections.

Such cheap I/O boards commonly have a 4 by 3 jumper matrix for the COM
ports, similar to the following:

                     o  o  o  *
         Port A               |
                     o  *  o  *
         Port B         |
                     o  *  o  o
         IRQ         2  3  4  5

Shown here is port A wired for IRQ 5 and port B wired for IRQ 3. The
IRQ columns on your specific board may vary - other boards may supply
jumpers for IRQs 3, 4, 5, and 7 instead.

One could conclude that wiring both ports for IRQ 3 using a handcrafted
wire-made jumper covering all three connection points in the IRQ 3
column would solve the issue, but nope: You cannot duplicate IRQ 3
because the output drivers of each UART are wired in a "totem pole"
fashion, so if one of the UARTs drives IRQ 3, the output signal won't be
what you would expect. Depending on the implementation of the extension
board or your motherboard, the IRQ 3 line will continuously stay up, or
always stay low.

Solution: You need to decouple the IRQ drivers for the two UARTs, so
that the IRQ line of the board only goes up if (and only if) one of
the UARTs asserts a IRQ, and stays low otherwise. The solution was
proposed by Jörg Wunsch <j@ida.interface-business.de>: To solder up a
wired-or consisting of two diodes (Germanium or Schottky-types strongly
preferred) and a 1 kOhm resistor. Here's the schematic, starting from
the 4 by 3 jumper field above:

                                   Diode
                         +---------->|-------+
                        /                    |
                     o  *  o  o              |     1 kOhm
         Port A                              +----|######|-------+
                     o  *  o  o              |                   |
         Port B          `-------------------+                 ==+==
                     o  *  o  o              |                 Ground
                         \                   |
                          +--------->|-------+
         IRQ         2  3  4  5    Diode

The cathodes of the diodes are connected to a common point, together
with a 1 kOhm pull-down resistor. It is essential to connect the
resistor to ground to avoid floating of the IRQ line on the bus.

Now we're ready to configure a kernel. Staying with this example, we would
configure:

        # standard on-board COM1 port
        device          sio0    at isa? port "IO_COM1" tty flags 0x10
        # patched-up multi-I/O extension board
        options         COM_MULTIPORT
        device          sio1    at isa? port "IO_COM2" tty flags 0x205
        device          sio2    at isa? port "IO_COM3" tty flags 0x205 irq 3

Note that the "flags" setting for sio1 and sio2 is truely essential;
refer to sio(4) for details. (Generally, the "2" in the "flags"
attribute refers to "sio2" which holds the IRQ, and you surely want a
"5" low nibble.) With kernel verbose mode turned on this should yield
something similar to this:

        sio0: irq maps: 0x1 0x11 0x1 0x1
        sio0 at 0x3f8-0x3ff irq 4 flags 0x10 on isa
        sio0: type 16550A
        sio1: irq maps: 0x1 0x9 0x1 0x1
        sio1 at 0x2f8-0x2ff flags 0x205 on isa
        sio1: type 16550A (multiport)
        sio2: irq maps: 0x1 0x9 0x1 0x1
        sio2 at 0x3e8-0x3ef irq 3 flags 0x205 on isa
        sio2: type 16550A (multiport master)

Though /sys/i386/isa/sio.c is somewhat cryptic with its use of the "irq
maps" array above, the basic idea is that you observe 0x1 in the first,
third, and fourth place. This means that the corresponding IRQ was set
upon output and cleared after, which is just what we would expect.
If your kernel doesn't display this behaviour, most likely there is
something wrong with your wiring.


Regards,
Helge


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




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