New section on using cheap multiport UARTS.
Submitted by: Helge Oldach <hmo@sep.hamburg.com>
This commit is contained in:
parent
e06812d8fa
commit
b52a94a043
Notes:
svn2git
2020-12-08 03:00:23 +00:00
svn path=/head/; revision=5731
2 changed files with 226 additions and 2 deletions
|
@ -1,7 +1,7 @@
|
|||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
|
||||
$FreeBSD$
|
||||
$FreeBSD: doc/en_US.ISO_8859-1/books/handbook/hw/chapter.sgml,v 1.26 1999/09/06 06:52:57 peter Exp $
|
||||
-->
|
||||
|
||||
<chapter id="hw">
|
||||
|
@ -2786,6 +2786,118 @@ sio16: type 16550A (multiport master)</screen>
|
|||
</step>
|
||||
</procedure>
|
||||
</sect4>
|
||||
|
||||
<sect4>
|
||||
<title>Support for Cheap Multi-UART Cards</title>
|
||||
|
||||
<para><emphasis>Contributed by Helge Oldach
|
||||
<email>hmo@sep.hamburg.com</email>, September
|
||||
1999</emphasis></para>
|
||||
|
||||
<para>Ever wondered about FreeBSD support for your 20$ multi-I/O
|
||||
card with two (or more) COM ports, sharing IRQs? Here's
|
||||
how:</para>
|
||||
|
||||
<para>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 <devicename>COM1</devicename> port (aka
|
||||
<devicename>sio0</devicename>–I/O address 0x3F8 and IRQ 4)
|
||||
and you have an extension board with two UARTs, you will commonly
|
||||
need to configure them as <devicename>COM2</devicename> (aka
|
||||
<devicename>sio1</devicename>–I/O address 0x2F8 and IRQ 3),
|
||||
and the third port (aka <devicename>sio2</devicename>) 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 <literal>COM_MULTIPORT</literal>
|
||||
configuration described in the previous sections.</para>
|
||||
|
||||
<para>Such cheap I/O boards commonly have a 4 by 3 jumper matrix for
|
||||
the COM ports, similar to the following:</para>
|
||||
|
||||
<programlisting> o o o *
|
||||
Port A |
|
||||
o * o *
|
||||
Port B |
|
||||
o * o o
|
||||
IRQ 2 3 4 5</programlisting>
|
||||
|
||||
<para>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.</para>
|
||||
|
||||
<para>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 no. 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 will not 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.</para>
|
||||
|
||||
<para>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 Jrg Wunsch
|
||||
<email>j@ida.interface-business.de</email>: To solder up a
|
||||
wired-or consisting of two diodes (Germanium or Schottky-types
|
||||
strongly preferred) and a 1 kOhm resistor. Here is the schematic,
|
||||
starting from the 4 by 3 jumper field above:</para>
|
||||
|
||||
<programlisting> Diode
|
||||
+---------->|-------+
|
||||
/ |
|
||||
o * o o | 1 kOhm
|
||||
Port A +----|######|-------+
|
||||
o * o o | |
|
||||
Port B `-------------------+ ==+==
|
||||
o * o o | Ground
|
||||
\ |
|
||||
+--------->|-------+
|
||||
IRQ 2 3 4 5 Diode</programlisting>
|
||||
|
||||
<para>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.</para>
|
||||
|
||||
<para>Now we are ready to configure a kernel. Staying with this
|
||||
example, we would configure:</para>
|
||||
|
||||
<programlisting># 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</programlisting>
|
||||
|
||||
<para>Note that the <literal>flags</literal> setting for
|
||||
<devicename>sio1</devicename> and <devicename>sio2</devicename> is
|
||||
truely essential; refer to
|
||||
&man.sio.4; for details. (Generally, the <literal>2</literal> in
|
||||
the "flags" attribute refers to <devicename>sio</devicename>2
|
||||
which holds the IRQ, and you surely want a <literal>5</literal>
|
||||
low nibble.) With kernel verbose mode turned on this should yield
|
||||
something similar to this:</para>
|
||||
|
||||
<screen>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)</screen>
|
||||
|
||||
<para>Though <filename>/sys/i386/isa/sio.c</filename> is somewhat
|
||||
cryptic with its use of the “irq maps” array above,
|
||||
the basic idea is that you observe <literal>0x1</literal> 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 does not display this behaviour, most
|
||||
likely there is something wrong with your wiring.</para>
|
||||
</sect4>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="cy">
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
<!--
|
||||
The FreeBSD Documentation Project
|
||||
|
||||
$FreeBSD$
|
||||
$FreeBSD: doc/en_US.ISO_8859-1/books/handbook/hw/chapter.sgml,v 1.26 1999/09/06 06:52:57 peter Exp $
|
||||
-->
|
||||
|
||||
<chapter id="hw">
|
||||
|
@ -2786,6 +2786,118 @@ sio16: type 16550A (multiport master)</screen>
|
|||
</step>
|
||||
</procedure>
|
||||
</sect4>
|
||||
|
||||
<sect4>
|
||||
<title>Support for Cheap Multi-UART Cards</title>
|
||||
|
||||
<para><emphasis>Contributed by Helge Oldach
|
||||
<email>hmo@sep.hamburg.com</email>, September
|
||||
1999</emphasis></para>
|
||||
|
||||
<para>Ever wondered about FreeBSD support for your 20$ multi-I/O
|
||||
card with two (or more) COM ports, sharing IRQs? Here's
|
||||
how:</para>
|
||||
|
||||
<para>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 <devicename>COM1</devicename> port (aka
|
||||
<devicename>sio0</devicename>–I/O address 0x3F8 and IRQ 4)
|
||||
and you have an extension board with two UARTs, you will commonly
|
||||
need to configure them as <devicename>COM2</devicename> (aka
|
||||
<devicename>sio1</devicename>–I/O address 0x2F8 and IRQ 3),
|
||||
and the third port (aka <devicename>sio2</devicename>) 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 <literal>COM_MULTIPORT</literal>
|
||||
configuration described in the previous sections.</para>
|
||||
|
||||
<para>Such cheap I/O boards commonly have a 4 by 3 jumper matrix for
|
||||
the COM ports, similar to the following:</para>
|
||||
|
||||
<programlisting> o o o *
|
||||
Port A |
|
||||
o * o *
|
||||
Port B |
|
||||
o * o o
|
||||
IRQ 2 3 4 5</programlisting>
|
||||
|
||||
<para>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.</para>
|
||||
|
||||
<para>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 no. 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 will not 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.</para>
|
||||
|
||||
<para>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 Jrg Wunsch
|
||||
<email>j@ida.interface-business.de</email>: To solder up a
|
||||
wired-or consisting of two diodes (Germanium or Schottky-types
|
||||
strongly preferred) and a 1 kOhm resistor. Here is the schematic,
|
||||
starting from the 4 by 3 jumper field above:</para>
|
||||
|
||||
<programlisting> Diode
|
||||
+---------->|-------+
|
||||
/ |
|
||||
o * o o | 1 kOhm
|
||||
Port A +----|######|-------+
|
||||
o * o o | |
|
||||
Port B `-------------------+ ==+==
|
||||
o * o o | Ground
|
||||
\ |
|
||||
+--------->|-------+
|
||||
IRQ 2 3 4 5 Diode</programlisting>
|
||||
|
||||
<para>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.</para>
|
||||
|
||||
<para>Now we are ready to configure a kernel. Staying with this
|
||||
example, we would configure:</para>
|
||||
|
||||
<programlisting># 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</programlisting>
|
||||
|
||||
<para>Note that the <literal>flags</literal> setting for
|
||||
<devicename>sio1</devicename> and <devicename>sio2</devicename> is
|
||||
truely essential; refer to
|
||||
&man.sio.4; for details. (Generally, the <literal>2</literal> in
|
||||
the "flags" attribute refers to <devicename>sio</devicename>2
|
||||
which holds the IRQ, and you surely want a <literal>5</literal>
|
||||
low nibble.) With kernel verbose mode turned on this should yield
|
||||
something similar to this:</para>
|
||||
|
||||
<screen>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)</screen>
|
||||
|
||||
<para>Though <filename>/sys/i386/isa/sio.c</filename> is somewhat
|
||||
cryptic with its use of the “irq maps” array above,
|
||||
the basic idea is that you observe <literal>0x1</literal> 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 does not display this behaviour, most
|
||||
likely there is something wrong with your wiring.</para>
|
||||
</sect4>
|
||||
</sect3>
|
||||
|
||||
<sect3 id="cy">
|
||||
|
|
Loading…
Reference in a new issue