<!DOCTYPE article PUBLIC "-//FreeBSD//DTD DocBook V4.1-Based Extension//EN" [
<!ENTITY % man PUBLIC "-//FreeBSD//ENTITIES DocBook Manual Page Entities//EN">
%man;
<!ENTITY % authors PUBLIC "-//FreeBSD//ENTITIES DocBook Author Entities//EN">
%authors;
]>

<article>
  <articleinfo>
    <title>Serial and UART Tutorial</title>
    
    <authorgroup>
      <author>
        <firstname>Frank</firstname>
        <surname>Durda</surname>
        
        <affiliation>
          <address><email>uhclem@FreeBSD.org</email></address>
        </affiliation>
      </author>
    </authorgroup>
    
    <pubdate>$FreeBSD$</pubdate>
    
    <abstract>
      <para>This article talks about using serial hardware with FreeBSD.</para>
    </abstract>
  </articleinfo>
  
  <sect1 id="uart">
    <title>The UART: What it is and how it works</title>

      <para><emphasis>Copyright &copy; 1996 &a.uhclem;, All Rights
        Reserved.  13 January 1996.</emphasis></para>

      <para>The Universal Asynchronous Receiver/Transmitter (UART)
	controller is the key component of the serial communications
	subsystem of a computer.  The UART takes bytes of data and
	transmits the individual bits in a sequential fashion.  At the
	destination, a second UART re-assembles the bits into complete
	bytes.</para>
	    
      <para>Serial transmission is commonly used with modems and for
	non-networked communication between computers, terminals and
	other devices.</para>
	    
      <para>There are two primary forms of serial transmission:
	Synchronous and Asynchronous.  Depending on the modes that are
	supported by the hardware, the name of the communication
	sub-system will usually include a <literal>A</literal> if it
	supports Asynchronous communications, and a
	<literal>S</literal> if it supports Synchronous
	communications.  Both forms are described below.</para>
	    
      <para>Some common acronyms are:</para>
	  
      <blockquote>
	<para>UART Universal Asynchronous Receiver/Transmitter</para>
      </blockquote>
	  
      <blockquote>
	<para>USART Universal Synchronous-Asynchronous
	  Receiver/Transmitter</para>
      </blockquote>

      <sect2>
        <title>Synchronous Serial Transmission</title>
	  
	<para>Synchronous serial transmission requires that the sender
	  and receiver share a clock with one another, or that the
	  sender provide a strobe or other timing signal so that the
	  receiver knows when to <quote>read</quote> the next bit of
	  the data.  In most forms of serial Synchronous
	  communication, if there is no data available at a given
	  instant to transmit, a fill character must be sent instead
	  so that data is always being transmitted.  Synchronous
	  communication is usually more efficient because only data
	  bits are transmitted between sender and receiver, and
	  synchronous communication can be more costly if extra wiring
	  and circuits are required to share a clock signal between
	  the sender and receiver.</para>
	      
	<para>A form of Synchronous transmission is used with printers
	  and fixed disk devices in that the data is sent on one set
	  of wires while a clock or strobe is sent on a different
	  wire. Printers and fixed disk devices are not normally
	  serial devices because most fixed disk interface standards
	  send an entire word of data for each clock or strobe signal
	  by using a separate wire for each bit of the word.  In the
	  PC industry, these are known as Parallel devices.</para>
	      
	<para>The standard serial communications hardware in the PC
	  does not support Synchronous operations.  This mode is
	  described here for comparison purposes only.</para>
      </sect2>

      <sect2>
        <title>Asynchronous Serial Transmission</title>
	  
	<para>Asynchronous transmission allows data to be transmitted
	  without the sender having to send a clock signal to the
	  receiver.  Instead, the sender and receiver must agree on
	  timing parameters in advance and special bits are added to
	  each word which are used to synchronize the sending and
	  receiving units.</para>
	      
	<para>When a word is given to the UART for Asynchronous
	  transmissions, a bit called the "Start Bit" is added to the
	  beginning of each word that is to be transmitted.  The Start
	  Bit is used to alert the receiver that a word of data is
	  about to be sent, and to force the clock in the receiver
	  into synchronization with the clock in the transmitter.
	  These two clocks must be accurate enough to not have the
	  frequency drift by more than 10% during the transmission of
	  the remaining bits in the word.  (This requirement was set
	  in the days of mechanical teleprinters and is easily met by
	  modern electronic equipment.)</para>
	      
	<para>After the Start Bit, the individual bits of the word of
	  data are sent, with the Least Significant Bit (LSB) being
	  sent first.  Each bit in the transmission is transmitted for
	  exactly the same amount of time as all of the other bits,
	  and the receiver <quote>looks</quote> at the wire at
	  approximately halfway through the period assigned to each
	  bit to determine if the bit is a <literal>1</literal> or a
	  <literal>0</literal>.  For example, if it takes two seconds
	  to send each bit, the receiver will examine the signal to
	  determine if it is a <literal>1</literal> or a
	  <literal>0</literal> after one second has passed, then it
	  will wait two seconds and then examine the value of the next
	  bit, and so on.</para>
	      
	<para>The sender does not know when the receiver has
	  <quote>looked</quote> at the value of the bit.  The sender
	  only knows when the clock says to begin transmitting the
	  next bit of the word.</para>
	      
	<para>When the entire data word has been sent, the transmitter
	  may add a Parity Bit that the transmitter generates.  The
	  Parity Bit may be used by the receiver to perform simple
	  error checking.  Then at least one Stop Bit is sent by the
	  transmitter.</para>
	      
	<para>When the receiver has received all of the bits in the
	  data word, it may check for the Parity Bits (both sender and
	  receiver must agree on whether a Parity Bit is to be used),
	  and then the receiver looks for a Stop Bit.  If the Stop Bit
	  does not appear when it is supposed to, the UART considers
	  the entire word to be garbled and will report a Framing
	  Error to the host processor when the data word is read.  The
	  usual cause of a Framing Error is that the sender and
	  receiver clocks were not running at the same speed, or that
	  the signal was interrupted.</para>
	      
	<para>Regardless of whether the data was received correctly or
	  not, the UART automatically discards the Start, Parity and
	  Stop bits.  If the sender and receiver are configured
	  identically, these bits are not passed to the host.</para>
	      
	<para>If another word is ready for transmission, the Start Bit
	  for the new word can be sent as soon as the Stop Bit for the
	  previous word has been sent.</para>
	      
	<para>Because asynchronous data is <quote>self
	  synchronizing</quote>, if there is no data to transmit, the
	  transmission line can be idle.</para>
      </sect2>

      <sect2>
        <title>Other UART Functions</title>
	  
	<para>In addition to the basic job of converting data from
	  parallel to serial for transmission and from serial to
	  parallel on reception, a UART will usually provide
	  additional circuits for signals that can be used to indicate
	  the state of the transmission media, and to regulate the
	  flow of data in the event that the remote device is not
	  prepared to accept more data.  For example, when the device
	  connected to the UART is a modem, the modem may report the
	  presence of a carrier on the phone line while the computer
	  may be able to instruct the modem to reset itself or to not
	  take calls by raising or lowering one more of these
	  extra signals. The function of each of these additional
	  signals is defined in the EIA RS232-C standard.</para>
      </sect2>

      <sect2>
        <title>The RS232-C and V.24 Standards</title>
	  
	<para>In most computer systems, the UART is connected to
	  circuitry that generates signals that comply with the EIA
	  RS232-C specification.  There is also a CCITT standard named
	  V.24 that mirrors the specifications included in
	  RS232-C.</para>
	      
	<sect3>
	  <title>RS232-C Bit Assignments (Marks and Spaces)</title>
	    
	  <para>In RS232-C, a value of <literal>1</literal> is called
	    a <literal>Mark</literal> and a value of
	    <literal>0</literal> is called a <literal>Space</literal>.
	    When a communication line is idle, the line is said to be
	    <quote>Marking</quote>, or transmitting continuous
	    <literal>1</literal> values.</para>
		
	  <para>The Start bit always has a value of
	    <literal>0</literal> (a Space).  The Stop Bit always has a
	    value of <literal>1</literal> (a Mark).  This means that
	    there will always be a Mark (1) to Space (0) transition on
	    the line at the start of every word, even when multiple
	    word are transmitted back to back.  This guarantees that
	    sender and receiver can resynchronize their clocks
	    regardless of the content of the data bits that are being
	    transmitted.</para>
		
	  <para>The idle time between Stop and Start bits does not
	    have to be an exact multiple (including zero) of the bit
	    rate of the communication link, but most UARTs are
	    designed this way for simplicity.</para>
		
	  <para>In RS232-C, the "Marking" signal (a
	    <literal>1</literal>) is represented by a voltage between
	    -2 VDC and -12 VDC, and a "Spacing" signal (a
	    <literal>0</literal>) is represented by a voltage between
	    0 and +12 VDC.  The transmitter is supposed to send +12
	    VDC or -12 VDC, and the receiver is supposed to allow for
	    some voltage loss in long cables.  Some transmitters in
	    low power devices (like portable computers) sometimes use
	    only +5 VDC and -5 VDC, but these values are still
	    acceptable to a RS232-C receiver, provided that the cable
	    lengths are short.</para>
	</sect3>
	      
	<sect3>
	  <title>RS232-C Break Signal</title>
	    
	  <para>RS232-C also specifies a signal called a
	    <literal>Break</literal>, which is caused by sending
	    continuous Spacing values (no Start or Stop bits).  When
	    there is no electricity present on the data circuit, the
	    line is considered to be sending
	    <literal>Break</literal>.</para>
		
	  <para>The <literal>Break</literal> signal must be of a
	    duration longer than the time it takes to send a complete
	    byte plus Start, Stop and Parity bits.  Most UARTs can
	    distinguish between a Framing Error and a Break, but if
	    the UART cannot do this, the Framing Error detection can
	    be used to identify Breaks.</para>
		
	  <para>In the days of teleprinters, when numerous printers
	    around the country were wired in series (such as news
	    services), any unit could cause a <literal>Break</literal>
	    by temporarily opening the entire circuit so that no
	    current flowed.  This was used to allow a location with
	    urgent news to interrupt some other location that was
	    currently sending information.</para>
		
	  <para>In modern systems there are two types of Break
	    signals. If the Break is longer than 1.6 seconds, it is
	    considered a "Modem Break", and some modems can be
	    programmed to terminate the conversation and go on-hook or
	    enter the modems' command mode when the modem detects this
	    signal.  If the Break is smaller than 1.6 seconds, it
	    signifies a Data Break and it is up to the remote computer
	    to respond to this signal.  Sometimes this form of Break
	    is used as an Attention or Interrupt signal and sometimes
	    is accepted as a substitute for the ASCII CONTROL-C
	    character.</para>
		
	  <para>Marks and Spaces are also equivalent to
	    <quote>Holes</quote> and <quote>No Holes</quote> in paper
	    tape systems.</para>

	  <note>
	    <para>Breaks cannot be generated from paper tape or from
	      any other byte value, since bytes are always sent with
	      Start and Stop bit.  The UART is usually capable of
	      generating the continuous Spacing signal in response to
	      a special command from the host processor.</para>
	  </note>
	</sect3>
	  
	<sect3>
	  <title>RS232-C DTE and DCE Devices</title>
	    
	  <para>The RS232-C specification defines two types of
	    equipment: the Data Terminal Equipment (DTE) and the Data
	    Carrier Equipment (DCE).  Usually, the DTE device is the
	    terminal (or computer), and the DCE is a modem.  Across
	    the phone line at the other end of a conversation, the
	    receiving modem is also a DCE device and the computer that
	    is connected to that modem is a DTE device.  The DCE
	    device receives signals on the pins that the DTE device
	    transmits on, and vice versa.</para>
		
	  <para>When two devices that are both DTE or both DCE must be
	    connected together without a modem or a similar media
	    translater between them, a NULL modem must be used.  The
	    NULL modem electrically re-arranges the cabling so that
	    the transmitter output is connected to the receiver input
	    on the other device, and vice versa.  Similar translations
	    are performed on all of the control signals so that each
	    device will see what it thinks are DCE (or DTE) signals
	    from the other device.</para>
		
	  <para>The number of signals generated by the DTE and DCE
	    devices are not symmetrical.  The DTE device generates
	    fewer signals for the DCE device than the DTE device
	    receives from the DCE.</para>
	</sect3>
	  
	<sect3>
	  <title>RS232-C Pin Assignments</title>
	    
	  <para>The EIA RS232-C specification (and the ITU equivalent,
	    V.24) calls for a twenty-five pin connector (usually a
	    DB25) and defines the purpose of most of the pins in that
	    connector.</para>
		
	  <para>In the IBM Personal Computer and similar systems, a
	    subset of RS232-C signals are provided via nine pin
	    connectors (DB9).  The signals that are not included on
	    the PC connector deal mainly with synchronous operation,
	    and this transmission mode is not supported by the UART
	    that IBM selected for use in the IBM PC.</para>
		
	  <para>Depending on the computer manufacturer, a DB25, a DB9,
	    or both types of connector may be used for RS232-C
	    communications.  (The IBM PC also uses a DB25 connector
	    for the parallel printer interface which causes some
	    confusion.)</para>
		
	  <para>Below is a table of the RS232-C signal assignments in
	    the DB25 and DB9 connectors.</para>

	  <informaltable frame="none">
	    <tgroup cols="7">
	      <thead>
	        <row>
		  <entry>DB25 RS232-C Pin</entry> <entry>DB9 IBM PC
		  Pin</entry> <entry>EIA Circuit Symbol</entry>
		  <entry>CCITT Circuit Symbol</entry> <entry>Common
		  Name</entry> <entry>Signal Source</entry>
		  <entry>Description</entry>
		</row>
	      </thead>
		
	      <tbody>
		<row>
		  <entry>1</entry>
		  <entry>-</entry>
		  <entry>AA</entry>
		  <entry>101</entry>
		  <entry>PG/FG</entry>
		  <entry>-</entry>
		  <entry>Frame/Protective Ground</entry>
		</row>
		  
		<row>
		  <entry>2</entry>
		  <entry>3</entry>
		  <entry>BA</entry>
		  <entry>103</entry>
		  <entry>TD</entry>
		  <entry>DTE</entry>
		  <entry>Transmit Data</entry>
		</row>
		  
		<row>
		  <entry>3</entry>
		  <entry>2</entry>
		  <entry>BB</entry>
		  <entry>104</entry>
		  <entry>RD</entry>
		  <entry>DCE</entry>
		  <entry>Receive Data</entry>
		</row>
		  
		<row>
		  <entry>4</entry>
		  <entry>7</entry>
		  <entry>CA</entry>
		  <entry>105</entry>
		  <entry>RTS</entry>
		  <entry>DTE</entry>
		  <entry>Request to Send</entry>
		</row>
		  
		<row>
		  <entry>5</entry>
		  <entry>8</entry>
		  <entry>CB</entry>
		  <entry>106</entry>
		  <entry>CTS</entry>
		  <entry>DCE</entry>
		  <entry>Clear to Send</entry>
		</row>
		  
		<row>
		  <entry>6</entry>
		  <entry>6</entry>
		  <entry>CC</entry>
		  <entry>107</entry>
		  <entry>DSR</entry>
		  <entry>DCE</entry>
		  <entry>Data Set Ready</entry>
		</row>
		  
		<row>
		  <entry>7</entry>
		  <entry>5</entry>
		  <entry>AV</entry>
		  <entry>102</entry>
		  <entry>SG/GND</entry>
		  <entry>-</entry>
		  <entry>Signal Ground</entry>
		</row>
		
		<row>
		  <entry>8</entry>
		  <entry>1</entry>
		  <entry>CF</entry>
		  <entry>109</entry>
		  <entry>DCD/CD</entry>
		  <entry>DCE</entry>
		  <entry>Data Carrier Detect</entry>
		</row>
		
		<row>
		  <entry>9</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>Reserved for Test</entry>
		</row>
		
		<row>
		  <entry>10</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>Reserved for Test</entry>
		</row>
		
		<row>
		  <entry>11</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>Reserved for Test</entry>
		</row>
		
		<row>
		  <entry>12</entry>
		  <entry>-</entry>
		  <entry>CI</entry>
		  <entry>122</entry>
		  <entry>SRLSD</entry>
		  <entry>DCE</entry>
		  <entry>Sec. Recv. Line Signal Detector</entry>
		</row>
		
		<row>
		  <entry>13</entry>
		  <entry>-</entry>
		  <entry>SCB</entry>
		  <entry>121</entry>
		  <entry>SCTS</entry>
		  <entry>DCE</entry>
		  <entry>Secondary Clear to Send</entry>
		</row>
		
		<row>
		  <entry>14</entry>
		  <entry>-</entry>
		  <entry>SBA</entry>
		  <entry>118</entry>
		  <entry>STD</entry>
		  <entry>DTE</entry>
		  <entry>Secondary Transmit Data</entry>
		</row>
		
		<row>
		  <entry>15</entry>
		  <entry>-</entry>
		  <entry>DB</entry>
		  <entry>114</entry>
		  <entry>TSET</entry>
		  <entry>DCE</entry>
		  <entry>Trans. Sig. Element Timing</entry>
		</row>
		
		<row>
		  <entry>16</entry>
		  <entry>-</entry>
		  <entry>SBB</entry>
		  <entry>119</entry>
		  <entry>SRD</entry>
		  <entry>DCE</entry>
		  <entry>Secondary Received Data</entry>
		</row>
		
		<row>
		  <entry>17</entry>
		  <entry>-</entry>
		  <entry>DD</entry>
		  <entry>115</entry>
		  <entry>RSET</entry>
		  <entry>DCE</entry>
		  <entry>Receiver Signal Element Timing</entry>
		</row>
		  
		<row>
		  <entry>18</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>141</entry>
		  <entry>LOOP</entry>
		  <entry>DTE</entry>
		  <entry>Local Loopback</entry>
		</row>
		
		<row>
		  <entry>19</entry>
		  <entry>-</entry>
		  <entry>SCA</entry>
		  <entry>120</entry>
		  <entry>SRS</entry>
		  <entry>DTE</entry>
		  <entry>Secondary Request to Send</entry>
		</row>
		
		<row>
		  <entry>20</entry>
		  <entry>4</entry>
		  <entry>CD</entry>
		  <entry>108.2</entry>
		  <entry>DTR</entry>
		  <entry>DTE</entry>
		  <entry>Data Terminal Ready</entry>
		</row>
		
		<row>
		  <entry>21</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>RDL</entry>
		  <entry>DTE</entry>
		  <entry>Remote Digital Loopback</entry>
		</row>
		
		<row>
		  <entry>22</entry>
		  <entry>9</entry>
		  <entry>CE</entry>
		  <entry>125</entry>
		  <entry>RI</entry>
		  <entry>DCE</entry>
		  <entry>Ring Indicator</entry>
		</row>
		
		<row>
		  <entry>23</entry>
		  <entry>-</entry>
		  <entry>CH</entry>
		  <entry>111</entry>
		  <entry>DSRS</entry>
		  <entry>DTE</entry>
		  <entry>Data Signal Rate Selector</entry>
		</row>
		
		<row>
		  <entry>24</entry>
		  <entry>-</entry>
		  <entry>DA</entry>
		  <entry>113</entry>
		  <entry>TSET</entry>
		  <entry>DTE</entry>
		  <entry>Trans. Sig. Element Timing</entry>
		</row>
		
		<row>
		  <entry>25</entry>
		  <entry>-</entry>
		  <entry>-</entry>
		  <entry>142</entry>
		  <entry>-</entry>
		  <entry>DCE</entry>
		  <entry>Test Mode</entry>
		</row>
	      </tbody>
	    </tgroup>
	  </informaltable>
	</sect3>
      </sect2>

      <sect2>
	<title>Bits, Baud and Symbols</title>
	  
	<para>Baud is a measurement of transmission speed in
	  asynchronous communication.  Because of advances in modem
	  communication technology, this term is frequently misused
	  when describing the data rates in newer devices.</para>
	      
	<para>Traditionally, a Baud Rate represents the number of bits
	  that are actually being sent over the media, not the amount
	  of data that is actually moved from one DTE device to the
	  other. The Baud count includes the overhead bits Start, Stop
	  and Parity that are generated by the sending UART and
	  removed by the receiving UART.  This means that seven-bit
	  words of data actually take 10 bits to be completely
	  transmitted.  Therefore, a modem capable of moving 300 bits
	  per second from one place to another can normally only move
	  30 7-bit words if Parity is used and one Start and Stop bit
	  are present.</para>
	      
	<para>If 8-bit data words are used and Parity bits are also
	  used, the data rate falls to 27.27 words per second, because
	  it now takes 11 bits to send the eight-bit words, and the
	  modem still only sends 300 bits per second.</para>
	      
	<para>The formula for converting bytes per second into a baud
	  rate and vice versa was simple until error-correcting modems
	  came along.  These modems receive the serial stream of bits
	  from the UART in the host computer (even when internal
	  modems are used the data is still frequently serialized) and
	  converts the bits back into bytes.  These bytes are then
	  combined into packets and sent over the phone line using a
	  Synchronous transmission method.  This means that the Stop,
	  Start, and Parity bits added by the UART in the DTE (the
	  computer) were removed by the modem before transmission by
	  the sending modem. When these bytes are received by the
	  remote modem, the remote modem adds Start, Stop and Parity
	  bits to the words, converts them to a serial format and then
	  sends them to the receiving UART in the remote computer, who
	  then strips the Start, Stop and Parity bits.</para>
	      
	<para>The reason all these extra conversions are done is so
	  that the two modems can perform error correction, which
	  means that the receiving modem is able to ask the sending
	  modem to resend a block of data that was not received with
	  the correct checksum.  This checking is handled by the
	  modems, and the DTE devices are usually unaware that the
	  process is occurring.</para>
	      
	<para>By striping the Start, Stop and Parity bits, the
	  additional bits of data that the two modems must share
	  between themselves to perform error-correction are mostly
	  concealed from the effective transmission rate seen by the
	  sending and receiving DTE equipment.  For example, if a
	  modem sends ten 7-bit words to another modem without
	  including the Start, Stop and Parity bits, the sending modem
	  will be able to add 30 bits of its own information that the
	  receiving modem can use to do error-correction without
	  impacting the transmission speed of the real data.</para>
	      
	<para>The use of the term Baud is further confused by modems
	  that perform compression.  A single 8-bit word passed over
	  the telephone line might represent a dozen words that were
	  transmitted to the sending modem.  The receiving modem will
	  expand the data back to its original content and pass that
	  data to the receiving DTE.</para>
	      
	<para>Modern modems also include buffers that allow the rate
	  that bits move across the phone line (DCE to DCE) to be a
	  different speed than the speed that the bits move between
	  the DTE and DCE on both ends of the conversation.  Normally
	  the speed between the DTE and DCE is higher than the DCE to
	  DCE speed because of the use of compression by the
	  modems.</para>
	      
	<para>Because the number of bits needed to describe a byte
	  varied during the trip between the two machines plus the
	  differing bits-per-seconds speeds that are used present on
	  the DTE-DCE and DCE-DCE links, the usage of the term Baud to
	  describe the overall communication speed causes problems and
	  can misrepresent the true transmission speed.  So Bits Per
	  Second (bps) is the correct term to use to describe the
	  transmission rate seen at the DCE to DCE interface and Baud
	  or Bits Per Second are acceptable terms to use when a
	  connection is made between two systems with a wired
	  connection, or if a modem is in use that is not performing
	  error-correction or compression.</para>
	      
	<para>Modern high speed modems (2400, 9600, 14,400, and
	  19,200bps) in reality still operate at or below 2400 baud,
	  or more accurately, 2400 Symbols per second.  High speed
	  modem are able to encode more bits of data into each Symbol
	  using a technique called Constellation Stuffing, which is
	  why the effective bits per second rate of the modem is
	  higher, but the modem continues to operate within the
	  limited audio bandwidth that the telephone system provides.
	  Modems operating at 28,800 and higher speeds have variable
	  Symbol rates, but the technique is the same.</para>
      </sect2>

      <sect2>
	<title>The IBM Personal Computer UART</title>
	  
	<para>Starting with the original IBM Personal Computer, IBM
	  selected the National Semiconductor INS8250 UART for use in
	  the IBM PC Parallel/Serial Adapter.  Subsequent generations
	  of compatible computers from IBM and other vendors continued
	  to use the INS8250 or improved versions of the National
	  Semiconductor UART family.</para>
	      
	<sect3>
	  <title>National Semiconductor UART Family Tree</title>
	    
	  <para>There have been several versions and subsequent
	    generations of the INS8250 UART.  Each major version is
	    described below.</para>

	    <!-- This should really be a graphic -->
	  <programlisting>INS8250  -&gt; INS8250B
  \
   \
    \-&gt; INS8250A -&gt; INS82C50A
             \
              \
               \-&gt; NS16450 -&gt; NS16C450
                        \
                         \
                          \-&gt; NS16550 -&gt; NS16550A -&gt; PC16550D</programlisting>
		
	  <variablelist>
	    <varlistentry>
	      <term>INS8250</term>

	      <listitem>
		<para>This part was used in the original IBM PC and
		  IBM PC/XT.  The original name for this part was the
		  INS8250 ACE (Asynchronous Communications Element)
		  and it is made from NMOS technology.</para>
			
		<para>The 8250 uses eight I/O ports and has a one-byte
		  send and a one-byte receive buffer.  This original
		  UART has several race conditions and other
		  flaws. The original IBM BIOS includes code to work
		  around these flaws, but this made the BIOS dependent
		  on the flaws being present, so subsequent parts like
		  the 8250A, 16450 or 16550 could not be used in the
		  original IBM PC or IBM PC/XT.</para>
	      </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>INS8250-B</term>
		
	      <listitem>
		<para>This is the slower speed of the INS8250 made
		  from NMOS technology.  It contains the same problems
		  as the original INS8250.</para>
	      </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>INS8250A</term>
		
	      <listitem>
		<para>An improved version of the INS8250 using XMOS
		  technology with various functional flaws
		  corrected. The INS8250A was used initially in PC
		  clone computers by vendors who used
		  <quote>clean</quote> BIOS designs. Because of the
		  corrections in the chip, this part could not be used
		  with a BIOS compatible with the INS8250 or
		  INS8250B.</para>
	      </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>INS82C50A</term>
		
	      <listitem>
		<para>This is a CMOS version (low power consumption)
		  of the INS8250A and has similar functional
		  characteristics.</para>
	      </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>NS16450</term>
		
	      <listitem>
		<para>Same as NS8250A with improvements so it can be
		  used with faster CPU bus designs.  IBM used this
		  part in the IBM AT and updated the IBM BIOS to no
		  longer rely on the bugs in the INS8250.</para>
              </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>NS16C450</term>
		
	      <listitem>
		<para>This is a CMOS version (low power consumption)
		  of the NS16450.</para>
              </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>NS16550</term>
		
	      <listitem>
		<para>Same as NS16450 with a 16-byte send and receive
		  buffer but the buffer design was flawed and could
		  not be reliably be used.</para>
	      </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>NS16550A</term>
		
	      <listitem>
		<para>Same as NS16550 with the buffer flaws
		  corrected. The 16550A and its successors have become
		  the most popular UART design in the PC industry,
		  mainly due it its ability to reliably handle higher
		  data rates on operating systems with sluggish
		  interrupt response times.</para>
	      </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>NS16C552</term>
		
	      <listitem>
		<para>This component consists of two NS16C550A CMOS
		  UARTs in a single package.</para>
	      </listitem>
	    </varlistentry>
	      
	    <varlistentry>
	      <term>PC16550D</term>
		
	      <listitem>
		<para>Same as NS16550A with subtle flaws
		  corrected. This is revision D of the 16550 family
		  and is the latest design available from National
		  Semiconductor.</para>
	      </listitem>
	    </varlistentry>
	  </variablelist>
	</sect3>
	  
	<sect3>
	  <title>The NS16550AF and the PC16550D are the same thing</title>
		
	  <para>National reorganized their part numbering system a few
	    years ago, and the NS16550AFN no longer exists by that
	    name. (If you have a NS16550AFN, look at the date code on
	    the part, which is a four digit number that usually starts
	    with a nine.  The first two digits of the number are the
	    year, and the last two digits are the week in that year
	    when the part was packaged.  If you have a NS16550AFN, it
	    is probably a few years old.)</para>
		
	  <para>The new numbers are like PC16550DV, with minor
	    differences in the suffix letters depending on the package
	    material and its shape.  (A description of the numbering
	    system can be found below.)</para>
		
	  <para>It is important to understand that in some stores, you
	    may pay &#36;15(US) for a NS16550AFN made in 1990 and in
	    the next bin are the new PC16550DN parts with minor fixes
	    that National has made since the AFN part was in
	    production, the PC16550DN was probably made in the past
	    six months and it costs half (as low as &#36;5(US) in
	    volume) as much as the NS16550AFN because they are readily
	    available.</para>
		
	  <para>As the supply of NS16550AFN chips continues to shrink,
	    the price will probably continue to increase until more
	    people discover and accept that the PC16550DN really has
	    the same function as the old part number.</para>
	</sect3>
	  
	<sect3>
	  <title>National Semiconductor Part Numbering System</title>
	    
	  <para>The older NS<replaceable>nnnnnrqp</replaceable> part
	    numbers are now of the format
	    PC<replaceable>nnnnnrgp</replaceable>.</para>
		
	  <para>The <replaceable>r</replaceable> is the revision
	    field.  The current revision of the 16550 from National
	    Semiconductor is <literal>D</literal>.</para>
		
	  <para>The <replaceable>p</replaceable> is the package-type
	    field.  The types are:</para>
	    
	  <informaltable frame="none">
	    <tgroup cols="3">
	      <tbody>
		<row>
		  <entry>"F"</entry>
		  <entry>QFP</entry>
		  <entry>(quad flat pack) L lead type</entry>
		</row>
		  
		<row>
		  <entry>"N"</entry>
		  <entry>DIP</entry>
		  <entry>(dual inline package) through hole straight lead
		    type</entry>
		</row>

		<row>
		  <entry>"V"</entry>
		  <entry>LPCC</entry>
		  <entry>(lead plastic chip carrier) J lead type</entry>
		</row>
	      </tbody>
	    </tgroup>
	  </informaltable>
	    
	  <para>The <replaceable>g</replaceable> is the product grade
	    field.  If an <literal>I</literal> precedes the
	    package-type letter, it indicates an
	    <quote>industrial</quote> grade part, which has higher
	    specs than a standard part but not as high as Military
	    Specification (Milspec) component.  This is an optional
	    field.</para>
		
	  <para>So what we used to call a NS16550AFN (DIP Package) is
	    now called a PC16550DN or PC16550DIN.</para>
        </sect3>
      </sect2>

      <sect2>
	<title>Other Vendors and Similar UARTs</title>
	  
	<para>Over the years, the 8250, 8250A, 16450 and 16550 have
	  been licensed or copied by other chip vendors.  In the case
	  of the 8250, 8250A and 16450, the exact circuit (the
	  <quote>megacell</quote>) was licensed to many vendors,
	  including Western Digital and Intel. Other vendors
	  reverse-engineered the part or produced emulations that had
	  similar behavior.</para>
	      
	<para>In internal modems, the modem designer will frequently
	  emulate the 8250A/16450 with the modem microprocessor, and
	  the emulated UART will frequently have a hidden buffer
	  consisting of several hundred bytes.  Because of the size of
	  the buffer, these emulations can be as reliable as a 16550A
	  in their ability to handle high speed data.  However, most
	  operating systems will still report that the UART is only a
	  8250A or 16450, and may not make effective use of the extra
	  buffering present in the emulated UART unless special
	  drivers are used.</para>
	      
	<para>Some modem makers are driven by market forces to abandon
	  a design that has hundreds of bytes of buffer and instead
	  use a 16550A UART so that the product will compare favorably
	  in market comparisons even though the effective performance
	  may be lowered by this action.</para>
	      
	<para>A common misconception is that all parts with
	  <quote>16550A</quote> written on them are identical in
	  performance.  There are differences, and in some cases,
	  outright flaws in most of these 16550A clones.</para>
	      
	<para>When the NS16550 was developed, the National
	  Semiconductor obtained several patents on the design and
	  they also limited licensing, making it harder for other
	  vendors to provide a chip with similar features.  Because of
	  the patents, reverse-engineered designs and emulations had
	  to avoid infringing the claims covered by the patents.
	  Subsequently, these copies almost never perform exactly the
	  same as the NS16550A or PC16550D, which are the parts most
	  computer and modem makers want to buy but are sometimes
	  unwilling to pay the price required to get the genuine
	  part.</para>
	      
	<para>Some of the differences in the clone 16550A parts are
	  unimportant, while others can prevent the device from being
	  used at all with a given operating system or driver.  These
	  differences may show up when using other drivers, or when
	  particular combinations of events occur that were not well
	  tested or considered in the Windows driver.  This is because
	  most modem vendors and 16550-clone makers use the Microsoft
	  drivers from Windows for Workgroups 3.11 and the Microsoft
	  MS-DOS utility as the primary tests for compatibility with
	  the NS16550A.  This over-simplistic criteria means that if a
	  different operating system is used, problems could appear
	  due to subtle differences between the clones and genuine
	  components.</para>
	      
	<para>National Semiconductor has made available a program
	  named <application>COMTEST</application> that performs
	  compatibility tests independent of any OS drivers.  It
	  should be remembered that the purpose of this type of
	  program is to demonstrate the flaws in the products of the
	  competition, so the program will report major as well as
	  extremely subtle differences in behavior in the part being
	  tested.</para>
	      
	<para>In a series of tests performed by the author of this
	  document in 1994, components made by National Semiconductor,
	  TI, StarTech, and CMD as well as megacells and emulations
	  embedded in internal modems were tested with COMTEST.  A
	  difference count for some of these components is listed
	  below. Because these tests were performed in 1994, they may
	  not reflect the current performance of the given product
	  from a vendor.</para>
	      
	<para>It should be noted that COMTEST normally aborts when an
	  excessive number or certain types of problems have been
	  detected.  As part of this testing, COMTEST was modified so
	  that it would not abort no matter how many differences were
	  encountered.</para>

	  <informaltable frame="none">
	    <tgroup cols="3">
	      <thead>
		<row>
		  <entry>Vendor</entry>
		  <entry>Part Number</entry>
		  <entry>Errors (aka "differences" reported)</entry>
		</row>
	      </thead>
	      
	      <tbody>
		<row>
		  <entry>National</entry>
		  <entry>(PC16550DV)</entry>
		  <entry>0</entry>
		</row>
		
		<row>
		  <entry>National</entry>
		  <entry>(NS16550AFN)</entry>
		  <entry>0</entry>
		</row>
		
		<row>
		  <entry>National</entry>
		  <entry>(NS16C552V)</entry>
		  <entry>0</entry>
		</row>
		
		<row>
		  <entry>TI</entry>
		  <entry>(TL16550AFN)</entry>
		  <entry>3</entry>
		</row>
		
		<row>
		  <entry>CMD</entry>
		  <entry>(16C550PE)</entry>
		  <entry>19</entry>
		</row>
		
		<row>
		  <entry>StarTech</entry>
		  <entry>(ST16C550J)</entry>
		  <entry>23</entry>
		</row>
		
		<row>
		  <entry>Rockwell</entry>
		  <entry>Reference modem with internal 16550 or an
		    emulation (RC144DPi/C3000-25)</entry>
		  <entry>117</entry>
		</row>
		
		<row>
		  <entry>Sierra</entry>
		  <entry>Modem with an internal 16550
		    (SC11951/SC11351)</entry>
		  <entry>91</entry>
		</row>
	      </tbody>
	    </tgroup>
	  </informaltable>
	  
	<note>
	  <para>To date, the author of this document has not found any
	    non-National parts that report zero differences using the
	    COMTEST program.  It should also be noted that National
	    has had five versions of the 16550 over the years and the
	    newest parts behave a bit differently than the classic
	    NS16550AFN that is considered the benchmark for
	    functionality.  COMTEST appears to turn a blind eye to the
	    differences within the National product line and reports
	    no errors on the National parts (except for the original
	    16550) even when there are official erratas that describe
	    bugs in the A, B and C revisions of the parts, so this
	    bias in COMTEST must be taken into account.</para>
	</note>
	  
	<para>It is important to understand that a simple count of
	  differences from COMTEST does not reveal a lot about what
	  differences are important and which are not.  For example,
	  about half of the differences reported in the two modems
	  listed above that have internal UARTs were caused by the
	  clone UARTs not supporting five- and six-bit character
	  modes.  The real 16550, 16450, and 8250 UARTs all support
	  these modes and COMTEST checks the functionality of these
	  modes so over fifty differences are reported.  However,
	  almost no modern modem supports five- or six-bit characters,
	  particularly those with error-correction and compression
	  capabilities.  This means that the differences related to
	  five- and six-bit character modes can be discounted.</para>
	      
	<para>Many of the differences COMTEST reports have to do with
	  timing.  In many of the clone designs, when the host reads
	  from one port, the status bits in some other port may not
	  update in the same amount of time (some faster, some slower)
	  as a <emphasis>real</emphasis> NS16550AFN and COMTEST looks
	  for these differences.  This means that the number of
	  differences can be misleading in that one device may only
	  have one or two differences but they are extremely serious,
	  and some other device that updates the status registers
	  faster or slower than the reference part (that would
	  probably never affect the operation of a properly written
	  driver) could have dozens of differences reported.</para>
	      
	<para>COMTEST can be used as a screening tool to alert the
	  administrator to the presence of potentially incompatible
	  components that might cause problems or have to be handled
	  as a special case.</para>
	      
	<para>If you run COMTEST on a 16550 that is in a modem or a
	  modem is attached to the serial port, you need to first
	  issue a ATE0&amp;W command to the modem so that the modem
	  will not echo any of the test characters.  If you forget to
	  do this, COMTEST will report at least this one
	  difference:</para>

	<screen>Error (6)...Timeout interrupt failed: IIR = c1  LSR = 61</screen>
      </sect2>

      <sect2>
	<title>8250/16450/16550 Registers</title>
	  
	<para>The 8250/16450/16550 UART occupies eight contiguous I/O
	  port addresses.  In the IBM PC, there are two defined
	  locations for these eight ports and they are known
	  collectively as COM1 and COM2.  The makers of PC-clones and
	  add-on cards have created two additional areas known as COM3
	  and COM4, but these extra COM ports conflict with other
	  hardware on some systems.  The most common conflict is with
	  video adapters that provide IBM 8514 emulation.</para>
	      
	<para>COM1 is located from 0x3f8 to 0x3ff and normally uses
	  IRQ 4 COM2 is located from 0x2f8 to 0x2ff and normally uses
	  IRQ 3 COM3 is located from 0x3e8 to 0x3ef and has no
	  standardized IRQ COM4 is located from 0x2e8 to 0x2ef and has
	  no standardized IRQ.</para>
	      
	<para>A description of the I/O ports of the 8250/16450/16550
	  UART is provided below.</para>

        <informaltable frame="none">
	  <tgroup cols="3">
	    <thead>
	      <row>
		<entry>I/O Port</entry>
		<entry>Access Allowed</entry>
		<entry>Description</entry>
	      </row>
	    </thead>
	      
	    <tbody>
	      <row>
		<entry>+0x00</entry>
		<entry>write (DLAB==0)</entry>
		<entry><para>Transmit Holding Register
		    (THR).</para><para>Information written to this port are
		    treated as data words and will be transmitted by the
		    UART.</para></entry>
	      </row>
		
	      <row>
		<entry>+0x00</entry>
		<entry>read (DLAB==0)</entry>
		<entry><para>Receive Buffer Register (RBR).</para><para>Any
		    data words received by the UART form the serial link are
		    accessed by the host by reading this
		    port.</para></entry>
	      </row>
		
	      <row>
		<entry>+0x00</entry>
		<entry>write/read (DLAB==1)</entry>
		<entry><para>Divisor Latch LSB (DLL)</para><para>This value
		      will be divided from the master input clock (in the IBM
		      PC, the master clock is 1.8432MHz) and the resulting
		      clock will determine the baud rate of the UART.  This
		      register holds bits 0 thru 7 of the
		      divisor.</para></entry>
	      </row>
		
	      <row>
		<entry>+0x01</entry>
		<entry>write/read (DLAB==1)</entry>
		<entry><para>Divisor Latch MSB (DLH)</para><para>This value
		      will be divided from the master input clock (in the IBM
		      PC, the master clock is 1.8432MHz) and the resulting
		      clock will determine the baud rate of the UART.  This
		      register holds bits 8 thru 15 of the
		      divisor.</para></entry>
	      </row>
		
	      <row>
		<entry>+0x01</entry>
		<entry>write/read (DLAB==0)</entry>
		<entrytbl cols="2">
		  <colspec colnum="1" colname="col1">
		  <colspec colnum="2" colname="col2">
		  <spanspec namest="col1" nameend="col2" spanname="1to2">

		  <tbody>
		    <row>
			<entry spanname="1to2"><para>Interrupt Enable Register
			    (IER)</para><para>The 8250/16450/16550 UART
			    classifies events into one of four categories.
			    Each category can be configured to generate an
			    interrupt when any of the events occurs.  The
			    8250/16450/16550 UART generates a single external
			    interrupt signal regardless of how many events in
			    the enabled categories have occurred.  It is up to
			    the host processor to respond to the interrupt and
			    then poll the enabled interrupt categories
			    (usually all categories have interrupts enabled)
			    to determine the true cause(s) of the
			    interrupt.</para></entry>
		    </row>
		      
		    <row>
		      <entry>Bit 7</entry>
		      <entry>Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 6</entry>
		      <entry>Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 5</entry>
		      <entry>Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 4</entry>
		      <entry>Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 3</entry>
		      <entry>Enable Modem Status Interrupt (EDSSI). Setting
			this bit to "1" allows the UART to generate an
			interrupt when a change occurs on one or more of the
			status lines.</entry>
		    </row>
		     
		    <row>
		      <entry>Bit 2</entry>
		      <entry>Enable Receiver Line Status Interrupt (ELSI)
			Setting this bit to "1" causes the UART to generate
			an interrupt when the an error (or a BREAK signal)
			has been detected in the incoming data.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 1</entry>
		      <entry>Enable Transmitter Holding Register Empty
			Interrupt (ETBEI) Setting this bit to "1" causes the
			UART to generate an interrupt when the UART has room
			for one or more additional characters that are to be
			transmitted.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 0</entry>
		      <entry>Enable Received Data Available Interrupt
			(ERBFI) Setting this bit to "1" causes the UART to
			generate an interrupt when the UART has received
			enough characters to exceed the trigger level of the
			FIFO, or the FIFO timer has expired (stale data), or
			a single character has been received when the FIFO
			is disabled.</entry>
		    </row>
		  </tbody>
		</entrytbl>
	      </row>
		
	      <row>
		<entry>+0x02</entry>
		<entry>write</entry>
		<entrytbl cols="4">
		  <colspec colnum="1" colname="col1">
		  <colspec colnum="2" colname="col2">
		  <colspec colnum="3" colname="col3">
		  <colspec colnum="4" colname="col4">
		  <spanspec namest="col1" nameend="col4" spanname="1to4">
		  <spanspec namest="col2" nameend="col4" spanname="2to4">
		   
		  <tbody>
		    <row>
		      <entry spanname="1to4">FIFO Control Register (FCR)
			(This port does not exist on the 8250 and 16450
			UART.)</entry>
		    </row>

		    <row>
		      <entry>Bit 7</entry>
		      <entry spanname="2to4">Receiver Trigger Bit #1</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 6</entry>
		      <entry spanname="2to4"><para>Receiver Trigger Bit
			#0</para><para>These two bits control at what
			point the receiver is to generate an interrupt
			when the FIFO is active.</para></entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">7</entry>
		      <entry colname="col3">6</entry>
		      <entry colname="col4">How many words are received
			before an interrupt is generated</entry>
		    </row>
			  
		    <row>
		      <entry colname="col2">0</entry>
		      <entry colname="col3">0</entry>
		      <entry colname="col4">1</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">0</entry>
		      <entry colname="col3">1</entry>
		      <entry colname="col4">4</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">1</entry>
		      <entry colname="col3">0</entry>
		      <entry colname="col4">8</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">1</entry>
		      <entry colname="col3">1</entry>
		      <entry colname="col4">14</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 5</entry>
		      <entry spanname="2to4">Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 4</entry>
		      <entry spanname="2to4">Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 3</entry>
		      <entry spanname="2to4">DMA Mode Select.  If Bit 0 is
			set to "1" (FIFOs enabled), setting this bit changes
			the operation of the -RXRDY and -TXRDY signals from
			Mode 0 to Mode 1.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 2</entry>
		      <entry spanname="2to4">Transmit FIFO Reset.  When a
			"1" is written to this bit, the contents of the FIFO
			are discarded.  Any word currently being transmitted
			will be sent intact.  This function is useful in
			aborting transfers.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 1</entry>
		      <entry spanname="2to4">Receiver FIFO Reset.  When a
			"1" is written to this bit, the contents of the FIFO
			are discarded.  Any word currently being assembled
			in the shift register will be received
			intact.</entry>
		    </row>

		    <row>
		      <entry>Bit 0</entry>
		      <entry spanname="2to4">16550 FIFO Enable.  When set,
			both the transmit and receive FIFOs are enabled.
			Any contents in the holding register, shift
			registers or FIFOs are lost when FIFOs are enabled
			or disabled.</entry>
		    </row>
		  </tbody>
		</entrytbl>
	      </row>
		
	      <row>
		<entry>+0x02</entry>
		<entry>read</entry>
		<entrytbl cols="6">
		  <colspec colnum="1" colname="col1">
		  <colspec colnum="2" colname="col2">
		  <colspec colnum="3" colname="col3">
		  <colspec colnum="4" colname="col4">
		  <colspec colnum="5" colname="col5">
		  <colspec colnum="6" colname="col6">
		  <spanspec namest="col1" nameend="col6" spanname="1to6">
		  <spanspec namest="col2" nameend="col6" spanname="2to6">

		  <tbody>
		    <row>
		      <entry spanname="1to6">Interrupt Identification
			Register</entry>
		    </row>

		    <row>
		      <entry>Bit 7</entry>
		      <entry spanname="2to6">FIFOs enabled.  On the
			8250/16450 UART, this bit is zero.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 6</entry>
		      <entry spanname="2to6">FIFOs enabled.  On the
			8250/16450 UART, this bit is zero.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 5</entry>
		      <entry spanname="2to6">Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 4</entry>
		      <entry spanname="2to6">Reserved, always 0.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 3</entry>
		      <entry spanname="2to6">Interrupt ID Bit #2.  On the
			8250/16450 UART, this bit is zero.</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 2</entry>
		      <entry spanname="2to6">Interrupt ID Bit #1</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 1</entry>
		      <entry spanname="2to6">Interrupt ID Bit #0.These
			three bits combine to report the category of
			event that caused the interrupt that is in
			progress.  These categories have priorities,
			so if multiple categories of events occur at
			the same time, the UART will report the more
			important events first and the host must
			resolve the events in the order they are
			reported.  All events that caused the current
			interrupt must be resolved before any new
			interrupts will be generated.  (This is a
			limitation of the PC architecture.)</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">2</entry>
		      <entry colname="col3">1</entry>
		      <entry colname="col4">0</entry>
		      <entry colname="col5">Priority</entry>
		      <entry colname="col6">Description</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">0</entry>
		      <entry colname="col3">1</entry>
		      <entry colname="col4">1</entry>
		      <entry colname="col5">First</entry>
		      <entry colname="col6">Received Error (OE, PE, BI, or
			FE)</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">0</entry>
		      <entry colname="col3">1</entry>
		      <entry colname="col4">0</entry>
		      <entry colname="col5">Second</entry>
		      <entry colname="col6">Received Data Available</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">1</entry>
		      <entry colname="col3">1</entry>
		      <entry colname="col4">0</entry>
		      <entry colname="col5">Second</entry>
		      <entry colname="col6">Trigger level identification
			(Stale data in receive buffer)</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">0</entry>
		      <entry colname="col3">0</entry>
		      <entry colname="col4">1</entry>
		      <entry colname="col5">Third</entry>
		      <entry colname="col6">Transmitter has room for more
			words (THRE)</entry>
		    </row>
		      
		    <row>
		      <entry colname="col2">0</entry>
		      <entry colname="col3">0</entry>
		      <entry colname="col4">0</entry>
		      <entry colname="col5">Fourth</entry>
		      <entry colname="col6">Modem Status Change (-CTS, -DSR,
			-RI, or -DCD)</entry>
		    </row>
		      
		    <row>
		      <entry>Bit 0</entry>
		      <entry spanname="2to6">Interrupt Pending Bit.  If this
			bit is set to "0", then at least one interrupt is
			pending.</entry>
		    </row>
		  </tbody>
		</entrytbl>
	        </row>
		
		<row>
		  <entry>+0x03</entry>
		  <entry>write/read</entry>
		  <entrytbl cols="5">
		    <colspec colnum="1" colname="col1">
		    <colspec colnum="2" colname="col2">
		    <colspec colnum="3" colname="col3">
		    <colspec colnum="4" colname="col4">
		    <colspec colnum="5" colname="col5">
		    <spanspec namest="col1" nameend="col5" spanname="1to5">
		    <spanspec namest="col2" nameend="col5" spanname="2to5">
		    <spanspec namest="col4" nameend="col5" spanname="4to5">

		    <tbody>
		      <row>
			<entry spanname="1to5">Line Control Register
			  (LCR)</entry>
		      </row>
		      
		      <row>
			<entry>Bit 7</entry>
			<entry spanname="2to5">Divisor Latch Access Bit
			  (DLAB).  When set, access to the data
			  transmit/receive register (THR/RBR) and the
			  Interrupt Enable Register (IER) is disabled.  Any
			  access to these ports is now redirected to the
			  Divisor Latch Registers.  Setting this bit, loading
			  the Divisor Registers, and clearing DLAB should be
			  done with interrupts disabled.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 6</entry>
			<entry spanname="2to5">Set Break.  When set to "1",
			  the transmitter begins to transmit continuous
			  Spacing until this bit is set to "0".  This
			  overrides any bits of characters that are being
			  transmitted.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 5</entry>
			<entry spanname="2to5">Stick Parity.  When parity is
			  enabled, setting this bit causes parity to always be
			  "1" or "0", based on the value of Bit 4.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 4</entry>
			<entry spanname="2to5">Even Parity Select (EPS). When
			  parity is enabled and Bit 5 is "0", setting this bit
			  causes even parity to be transmitted and expected.
			  Otherwise, odd parity is used.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 3</entry>
			<entry spanname="2to5">Parity Enable (PEN).  When set
			  to "1", a parity bit is inserted between the last
			  bit of the data and the Stop Bit.  The UART will
			  also expect parity to be present in the received
			  data.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 2</entry>
			<entry spanname="2to5">Number of Stop Bits (STB). If
			  set to "1" and using 5-bit data words, 1.5 Stop Bits
			  are transmitted and expected in each data word.  For
			  6, 7 and 8-bit data words, 2 Stop Bits are
			  transmitted and expected.  When this bit is set to
			  "0", one Stop Bit is used on each data word.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 1</entry>
			<entry spanname="2to5">Word Length Select Bit #1
			  (WLSB1)</entry>
		      </row>
		      
		      <row>
			<entry>Bit 0</entry>
			<entry spanname="2to5">Word Length Select Bit #0
			  (WLSB0)</entry>
		      </row>
		      
		      <row>
			<entry colname="col2" spanname="2to5">Together these
			  bits specify the number of bits in each data
			  word.</entry>
		      </row>
		      
		      <row>
			<entry colname="col2">1</entry>
			<entry colname="col3">0</entry>
			<entry colname="col4" spanname="4to5">Word
			  Length</entry>
		      </row>
		      
		      <row>
			<entry colname="col2">0</entry>
			<entry colname="col3">0</entry>
			<entry colname="col4" spanname="4to5">5 Data
			  Bits</entry>
		      </row>
		      
		      <row>
			<entry colname="col2">0</entry>
			<entry colname="col3">1</entry>
			<entry colname="col4" spanname="4to5">6 Data
			  Bits</entry>
		      </row>
		      
		      <row>
			<entry colname="col2">1</entry>
			<entry colname="col3">0</entry>
			<entry colname="col4" spanname="4to5">7 Data
			  Bits</entry>
		      </row>
		      
		      <row>
			<entry colname="col2">1</entry>
			<entry colname="col3">1</entry>
			<entry colname="col4" spanname="4to5">8 Data
			  Bits</entry>
		      </row>
		    </tbody>
		  </entrytbl>
		</row>
		
		<row>
		  <entry>+0x04</entry>
		  <entry>write/read</entry>
		  <entrytbl cols="2">
		    <colspec colnum="1" colname="col1">
		    <colspec colnum="2" colname="col2">
		    <spanspec namest="col1" nameend="col2" spanname="1to2">

		    <tbody>
		      <row>
			<entry spanname="1to2">Modem Control Register
			  (MCR)</entry>
		      </row>
		      
		      <row>
			<entry>Bit 7</entry>
			<entry>Reserved, always 0.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 6</entry>
			<entry>Reserved, always 0.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 5</entry>
			<entry>Reserved, always 0.</entry>
			  </row>
		      
		      <row>
			<entry>Bit 4</entry>
			<entry>Loop-Back Enable.  When set to "1", the UART
			  transmitter and receiver are internally connected
			  together to allow diagnostic operations.  In
			  addition, the UART modem control outputs are
			  connected to the UART modem  control inputs.  CTS is
			  connected to RTS, DTR is connected to DSR, OUT1 is
			  connected to RI, and OUT 2 is connected to
			  DCD.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 3</entry>
			<entry>OUT 2.  An auxiliary output that the host
			  processor may set high or low.  In the IBM PC serial
			  adapter (and most clones), OUT 2 is used to
			  tri-state (disable) the interrupt signal from the
			  8250/16450/16550 UART.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 2</entry>
			<entry>OUT 1.  An auxiliary output that the host
			  processor may set high or low.  This output is not
			  used on the IBM PC serial adapter.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 1</entry>
			<entry>Request to Send (RTS).  When set to "1", the
			  output of the UART -RTS line is Low
			  (Active).</entry>
		      </row>
		      
		      <row>
			<entry>Bit 0</entry>
			<entry>Data Terminal Ready (DTR).  When set to "1",
			  the output of the UART -DTR line is Low
			  (Active).</entry>
		      </row>
		    </tbody>
		  </entrytbl>
		</row>
		
		<row>
		  <entry>+0x05</entry>
		  <entry>write/read</entry>
		  <entrytbl cols="2">
		    <colspec colnum="1" colname="col1">
		    <colspec colnum="2" colname="col2">
		    <spanspec namest="col1" nameend="col2" spanname="1to2">

		    <tbody>
		      <row>
			<entry spanname="1to2">Line Status Register
			  (LSR)</entry>
		      </row>
		      
		      <row>
			<entry>Bit 7</entry>
			<entry>Error in Receiver FIFO.  On the 8250/16450
			  UART, this bit is zero.  This bit is set to "1" when
			  any of the bytes in the FIFO have one or more of the
			  following error conditions: PE, FE, or BI.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 6</entry>
			<entry>Transmitter Empty (TEMT).  When set to "1",
			  there are no words  remaining in the transmit FIFO
			  or the transmit shift register.  The transmitter is
			  completely idle.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 5</entry>
			<entry>Transmitter Holding Register Empty (THRE).
			  When set to "1", the FIFO (or holding register) now
			  has room for at least one additional word to
			  transmit.  The transmitter may still be transmitting
			  when this bit is set to "1".</entry>
		      </row>
		      
		      <row>
			<entry>Bit 4</entry>
			<entry>Break Interrupt (BI).  The receiver has
			  detected a Break signal.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 3</entry>
			<entry>Framing Error (FE).  A Start Bit was detected
			  but the Stop Bit did not appear at the expected
			  time.  The received word is probably
			  garbled.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 2</entry>
			<entry>Parity Error (PE).  The parity bit was
			  incorrect for the word received.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 1</entry>
			<entry>Overrun Error (OE).  A new word was received
			  and there was no room in the receive buffer.  The
			  newly-arrived word in the shift register is
			  discarded.  On 8250/16450 UARTs, the word in the
			  holding register is discarded and the newly- arrived
			  word is put in the holding register.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 0</entry>
			<entry>Data Ready (DR) One or more words are in the
			  receive FIFO that the host may read.  A word must be
			  completely received and moved from the shift
			  register into the FIFO (or holding register for
			  8250/16450 designs) before this bit is set.</entry>
		      </row>
		    </tbody>
		  </entrytbl>
		</row>
		
		<row>
		  <entry>+0x06</entry>
		  <entry>write/read</entry>
		  <entrytbl cols="2">
		    <colspec colnum="1" colname="col1">
		    <colspec colnum="2" colname="col2">
		    <spanspec namest="col1" nameend="col2" spanname="1to2">

		    <tbody>
		      <row>
			<entry spanname="1to2">Modem Status Register
			  (MSR)</entry>
		      </row>
		      
		      <row>
			<entry>Bit 7</entry>
			<entry>Data Carrier Detect (DCD).  Reflects the state
			  of the DCD line on the UART.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 6</entry>
			<entry>Ring Indicator (RI).  Reflects the state of the
			  RI line on the UART.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 5</entry>
			<entry>Data Set Ready (DSR).  Reflects the state of
			  the DSR line on the UART.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 4</entry>
			<entry>Clear To Send (CTS).  Reflects the state of the
			  CTS line on the UART.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 3</entry>
			<entry>Delta Data Carrier Detect (DDCD).  Set to "1"
			  if the -DCD line has changed state one more
			  time since the last time the MSR was read by the
			  host.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 2</entry>
			<entry>Trailing Edge Ring Indicator (TERI).  Set to
			  "1" if the -RI line has had a low to high transition
			  since the last time the MSR was read by the
			  host.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 1</entry>
			<entry>Delta Data Set Ready (DDSR).  Set to "1" if the
			  -DSR line has changed state one more time
			  since the last time the MSR was read by the
			  host.</entry>
		      </row>
		      
		      <row>
			<entry>Bit 0</entry>
			<entry>Delta Clear To Send (DCTS).  Set to "1" if the
			  -CTS line has changed state one more time
			  since the last time the MSR was read by the
			  host.</entry>
		      </row>
		    </tbody>
		  </entrytbl>
		</row>
		
		<row>
		  <entry>+0x07</entry>
		  <entry>write/read</entry>
		  <entry>Scratch Register (SCR).  This register performs no
		    function in the UART.  Any value can be written by the
		    host to this location and read by the host later
		    on.</entry>
		</row>
	      </tbody>
	    </tgroup>
	  </informaltable>
      </sect2>

      <sect2>
	<title>Beyond the 16550A UART</title>
	  
	<para>Although National Semiconductor has not offered any
	  components compatible with the 16550 that provide additional
	  features, various other vendors have.  Some of these
	  components are described below.  It should be understood
	  that to effectively utilize these improvements, drivers may
	  have to be provided by the chip vendor since most of the
	  popular operating systems do not support features beyond
	  those provided by the 16550.</para>
	      
	  <variablelist>
	    <varlistentry>
	      <term>ST16650</term>

	      <listitem>
		<para>By default this part is similar to the NS16550A, but an
		  extended 32-byte send and receive buffer can be optionally
		  enabled.  Made by StarTech.</para>
	      </listitem>
	    </varlistentry>
	    
	    <varlistentry>
	      <term>TIL16660</term>
	      
	      <listitem>
		<para>By default this part behaves similar to the NS16550A,
		  but an extended 64-byte send and receive buffer can be
		  optionally enabled.  Made by Texas Instruments.</para>
	      </listitem>
	    </varlistentry>
	    
	    <varlistentry>
	      <term>Hayes ESP</term>
	      
	      <listitem>
		<para>This proprietary plug-in card contains a 2048-byte send
		  and receive buffer, and supports data rates to
		  230.4Kbit/sec.  Made by Hayes.</para>
	      </listitem>
	    </varlistentry>
	  </variablelist>
	  
	  <para>In addition to these <quote>dumb</quote> UARTs, many vendors
	    produce intelligent serial communication boards.  This type of
	    design usually provides a microprocessor that interfaces with
	    several UARTs, processes and buffers the data, and then alerts the
	    main PC processor when necessary.  Because the UARTs are not
	    directly accessed by the PC processor in this type of
	    communication system, it is not necessary for the vendor to use
	    UARTs that are compatible with the 8250, 16450, or the 16550 UART.
	    This leaves the designer free to components that may have better
	    performance characteristics.</para>
      </sect2>
    </sect1>
      
    <sect1 id="sio">
      <title>Configuring the <devicename>sio</devicename> driver</title>
	    
      <para>The <devicename>sio</devicename> driver provides support
	for NS8250-, NS16450-, NS16550 and NS16550A-based EIA RS-232C
	(CCITT V.24) communications interfaces.  Several multiport
	cards are supported as well.  See the &man.sio.4; manual page
	for detailed technical documentation.</para>
	    
      <sect2>
	<title>Digi International (DigiBoard) PC/8</title>
	  
	<para><emphasis>Contributed by &a.awebster;.  26 August
	  1995.</emphasis></para>
	      
        <para>Here is a config snippet from a machine with a Digi
	  International PC/8 with 16550.  It has 8 modems connected to
	  these 8 lines, and they work just great.  Do not forget to
	  add <literal>options COM_MULTIPORT</literal> or it will not
	  work very well!</para>
	      
	<programlisting>device          sio4    at isa? port 0x100 flags 0xb05
device          sio5    at isa? port 0x108 flags 0xb05
device          sio6    at isa? port 0x110 flags 0xb05
device          sio7    at isa? port 0x118 flags 0xb05
device          sio8    at isa? port 0x120 flags 0xb05
device          sio9    at isa? port 0x128 flags 0xb05
device          sio10   at isa? port 0x130 flags 0xb05
device          sio11   at isa? port 0x138 flags 0xb05 irq 9</programlisting>
	      
	<para>The trick in setting this up is that the MSB of the
	  flags represent the last SIO port, in this case 11 so flags
	  are 0xb05.</para>
      </sect2>

      <sect2>
	<title>Boca 16</title>
	  
	<para><emphasis>Contributed by &a.whiteside;.  26 August
	  1995.</emphasis></para>
	  
	<para>The procedures to make a Boca 16 port board with FreeBSD
	  are pretty straightforward, but you will need a couple
	  things to make it work:</para>
	  
	<orderedlist>
	  <listitem>
	    <para>You either need the kernel sources installed so you
		can recompile the necessary options or you will need
		someone else to compile it for you.  The 2.0.5 default
		kernel does <emphasis>not</emphasis> come with
		multiport support enabled and you will need to add a
		device entry for each port anyways.</para>
	  </listitem>
	    
	  <listitem>
	    <para>Two, you will need to know the interrupt and IO
	      setting for your Boca Board so you can set these options
	      properly in the kernel.</para>
	  </listitem>
	</orderedlist>
	  
	<para>One important note &mdash; the actual UART chips for the
	  Boca 16 are in the connector box, not on the internal board
	  itself.  So if you have it unplugged, probes of those ports
	  will fail.  I have never tested booting with the box
	  unplugged and plugging it back in, and I suggest you do not
	  either.</para>
	      
        <para>If you do not already have a custom kernel
	  configuration file set up, refer to <ulink
	  url="../../books/handbook/kernelconfig.html">Kernel
	  Configuration</ulink> chapter of the FreeBSD Handbook for
	  general procedures.  The following are the specifics for the
	  Boca 16 board and assume you are using the kernel name
	  MYKERNEL and editing with vi.</para>
	      
	<procedure>
	  <step>
	    <para>Add the line 
		
	      <programlisting>options COM_MULTIPORT</programlisting>

	      to the config file.</para>
	  </step>
	    
	  <step>
	    <para>Where the current <literal>device
	      sio<replaceable>n</replaceable></literal> lines are, you
	      will need to add 16 more devices.  The
	      following example is for a Boca Board with an interrupt
	      of 3, and a base IO address 100h.  The IO address for
	      Each port is +8 hexadecimal from the previous port, thus
	      the 100h, 108h, 110h...  addresses.</para>

	    <programlisting>device sio1 at isa? port 0x100 flags 0x1005
device sio2 at isa? port 0x108 flags 0x1005
device sio3 at isa? port 0x110 flags 0x1005
device sio4 at isa? port 0x118 flags 0x1005
&hellip;
device sio15 at isa? port 0x170 flags 0x1005
device sio16 at isa? port 0x178 flags 0x1005 irq 3</programlisting>

	    <para>The flags entry <emphasis>must</emphasis> be changed
	      from this example unless you are using the exact same
	      sio assignments. Flags are set according to
	      0x<replaceable>M</replaceable><replaceable>YY</replaceable>
	      where <replaceable>M</replaceable> indicates the minor
	      number of the master port (the last port on a Boca 16)
	      and <replaceable>YY</replaceable> indicates if FIFO is
	      enabled or disabled(enabled), IRQ sharing is used(yes)
	      and if there is an AST/4 compatible IRQ control
	      register(no).  In this example, <programlisting> flags
	      0x1005</programlisting> indicates that the master port
	      is sio16.  If I added another board and assigned sio17
	      through sio28, the flags for all 16 ports on
	      <emphasis>that</emphasis> board would be 0x1C05, where
	      1C indicates the minor number of the master port.  Do
	      not change the 05 setting.</para>
	  </step>
		  
	  <step>
	    <para>Save and complete the kernel configuration,
	      recompile, install and reboot.  Presuming you have
	      successfully installed the recompiled kernel and have it
	      set to the correct address and IRQ, your boot message
	      should indicate the successful probe of the Boca ports
	      as follows: (obviously the sio numbers, IO and IRQ could
	      be different)</para>
		    		    
	    <screen>sio1 at 0x100-0x107 flags 0x1005 on isa
sio1: type 16550A (multiport)
sio2 at 0x108-0x10f flags 0x1005 on isa
sio2: type 16550A (multiport)
sio3 at 0x110-0x117 flags 0x1005 on isa
sio3: type 16550A (multiport)
sio4 at 0x118-0x11f flags 0x1005 on isa
sio4: type 16550A (multiport)
sio5 at 0x120-0x127 flags 0x1005 on isa
sio5: type 16550A (multiport)
sio6 at 0x128-0x12f flags 0x1005 on isa
sio6: type 16550A (multiport)
sio7 at 0x130-0x137 flags 0x1005 on isa
sio7: type 16550A (multiport)
sio8 at 0x138-0x13f flags 0x1005 on isa
sio8: type 16550A (multiport)
sio9 at 0x140-0x147 flags 0x1005 on isa
sio9: type 16550A (multiport)
sio10 at 0x148-0x14f flags 0x1005 on isa
sio10: type 16550A (multiport)
sio11 at 0x150-0x157 flags 0x1005 on isa
sio11: type 16550A (multiport)
sio12 at 0x158-0x15f flags 0x1005 on isa
sio12: type 16550A (multiport)
sio13 at 0x160-0x167 flags 0x1005 on isa
sio13: type 16550A (multiport)
sio14 at 0x168-0x16f flags 0x1005 on isa
sio14: type 16550A (multiport)
sio15 at 0x170-0x177 flags 0x1005 on isa
sio15: type 16550A (multiport)
sio16 at 0x178-0x17f irq 3 flags 0x1005 on isa
sio16: type 16550A (multiport master)</screen>

	    <para>If the messages go by too fast to see,

	    <screen>&prompt.root; <userinput>dmesg | more</userinput></screen>
	      will show you the boot messages.</para>
	  </step>
	    
	  <step>
	    <para>Next, appropriate entries in
	      <filename>/dev</filename> for the devices must be made
	      using the <filename>/dev/MAKEDEV</filename>
	      script. After becoming root:</para>
	      
	    <screen>&prompt.root; <userinput>cd /dev</userinput>
&prompt.root; <userinput>./MAKEDEV tty1</userinput>
&prompt.root; <userinput>./MAKEDEV cua1</userinput>
<emphasis>(everything in between)</emphasis>
&prompt.root; <userinput>./MAKEDEV ttyg</userinput>
&prompt.root; <userinput>./MAKEDEV cuag</userinput></screen>
		      
	    <para>If you do not want or need call-out devices for some
	      reason, you can dispense with making the
	      <filename>cua*</filename> devices.</para>
	  </step>
	    
	  <step>
	    <para>If you want a quick and sloppy way to make sure the
	      devices are working, you can simply plug a modem into
	      each port and (as root)
		    
            <screen>&prompt.root; <userinput>echo at &gt; ttyd*</userinput></screen>
	      for each device you have made.  You
	      <emphasis>should</emphasis> see the RX lights flash for each
	      working port.</para>
	  </step>
	</procedure>
      </sect2>

      <sect2>
	<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 is 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>&ndash;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>&ndash;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 resources, 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&mdash;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 <quote>totem
	  pole</quote> 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 Joerg 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" flags 0x10
# patched-up multi-I/O extension board
options         COM_MULTIPORT
device          sio1    at isa? port "IO_COM2" flags 0x205
device          sio2    at isa? port "IO_COM3" flags 0x205 irq 3</programlisting>

	<para>Note that the <literal>flags</literal> setting for
	  <devicename>sio1</devicename> and
	  <devicename>sio2</devicename> is truly 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 <quote>irq maps</quote>
	  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 behavior, most
	  likely there is something wrong with your wiring.</para>
      </sect2>
    </sect1>
      
    <sect1 id="cy">
      <title>Configuring the <devicename>cy</devicename> driver</title>
	    
      <para><emphasis>Contributed by Alex Nash.  6 June
        1996.</emphasis></para>
	    
      <para>The Cyclades multiport cards are based on the
	<devicename>cy</devicename> driver instead of the usual
	<devicename>sio</devicename> driver used by other multiport
	cards.  Configuration is a simple matter of:</para>

	<procedure>
	  <step>
	    <para>Add the <devicename>cy</devicename> device to your
	      kernel configuration (note that your irq and iomem
	      settings may differ).</para>
		    
	    <programlisting>device cy0 at isa? irq 10 iomem 0xd4000 iosiz 0x2000</programlisting>
	  </step>
		
	  <step>
	    <para>Rebuild and install the new kernel.</para>
	  </step>
	  
	  <step>
	    <para>Make the device nodes by typing (the following
	      example assumes an 8-port board):</para>
		  
	    <screen>&prompt.root; <userinput>cd /dev</userinput>
&prompt.root; <userinput>for i in 0 1 2 3 4 5 6 7;do ./MAKEDEV cuac$i ttyc$i;done</userinput></screen>
	  </step>
	  
	  <step>
	    <para>If appropriate, add dialup entries to
	      <filename>/etc/ttys</filename> by duplicating serial
	      device (<literal>ttyd</literal>) entries and using
	      <literal>ttyc</literal> in place of
	      <literal>ttyd</literal>.  For example:</para>
	    
	    <programlisting>ttyc0   "/usr/libexec/getty std.38400"  unknown on insecure
ttyc1   "/usr/libexec/getty std.38400"  unknown on insecure
ttyc2   "/usr/libexec/getty std.38400"  unknown on insecure
&hellip;
ttyc7   "/usr/libexec/getty std.38400"  unknown on insecure</programlisting>
	  </step>
		
	  <step>
	    <para>Reboot with the new kernel.</para>
	  </step>
	</procedure>
    </sect1>

    <sect1>
      <title>Configuring the <devicename>si</devicename> driver</title>

      <para><emphasis>Contributed by &a.nsayer;. 25 March
	1998.</emphasis></para>
     
      <para>The Specialix SI/XIO and SX multiport cards use the
	<devicename>si</devicename> driver. A single machine can have
	up to 4 host cards. The following host cards are
	supported:</para>

	<itemizedlist>
	  <listitem><para>ISA SI/XIO host card (2 versions)</para></listitem>
	  <listitem><para>EISA SI/XIO host card</para></listitem>
	  <listitem><para>PCI SI/XIO host card</para></listitem>
	  <listitem><para>ISA SX host card</para></listitem>
	  <listitem><para>PCI SX host card</para></listitem>
	</itemizedlist>

      <para>Although the SX and SI/XIO host cards look markedly
	different, their functionality are basically the same. The
	host cards do not use I/O locations, but instead require a 32K
	chunk of memory. The factory configuration for ISA cards
	places this at <literal>0xd0000-0xd7fff</literal>.  They also
	require an IRQ. PCI cards will, of course, auto-configure
	themselves.</para>

      <para>You can attach up to 4 external modules to each host
	card. The external modules contain either 4 or 8 serial
	ports. They come in the following varieties:</para>

	<itemizedlist>
	  <listitem><para>SI 4 or 8 port modules. Up to 57600 bps on each port
	      supported.</para></listitem>
	  
	  <listitem><para>XIO 8 port modules. Up to 115200 bps on each port
	      supported. One type of XIO module has 7 serial and 1 parallel
	      port.</para></listitem>
	  
	  <listitem><para>SXDC 8 port modules. Up to 921600 bps on each port
	      supported. Like XIO, a module is available with one parallel
	      port as well.</para></listitem>
	</itemizedlist>

      <para>To configure an ISA host card, add the following line to
	your kernel configuration file, changing the numbers as
	appropriate:</para>
     
      <programlisting>device si0 at isa? iomem 0xd0000 irq 11</programlisting>

      <para>Valid IRQ numbers are 9, 10, 11, 12 and 15 for SX ISA host
	cards and 11, 12 and 15 for SI/XIO ISA host cards.</para>
     
      <para>To configure an EISA or PCI host card, use this line:</para>
     
      <programlisting>device si0</programlisting>

      <para>After adding the configuration entry, rebuild and
	install your new kernel.</para>
     
      <para>After rebooting with the new kernel, you need to make the
	device nodes in /dev. The <filename>MAKEDEV</filename> script
	will take care of this for you.  Count how many total ports
	you have and type:</para>
     
      <screen>&prompt.root; <userinput>cd /dev</userinput>
&prompt.root; <userinput>./MAKEDEV ttyA<replaceable>nn</replaceable> cuaA<replaceable>nn</replaceable></userinput></screen>
     
      <para>(where <replaceable>nn</replaceable> is the number of
	ports)</para>
     
      <para>If you want login prompts to appear on these ports, you
	will need to add lines like this to
	<filename>/etc/ttys</filename>:</para>

      <programlisting>ttyA01  "/usr/libexec/getty std.9600"   vt100   on insecure</programlisting>
     
      <para>Change the terminal type as appropriate. For modems,
	<userinput>dialup</userinput> or
	<userinput>unknown</userinput> is fine.</para>

  </sect1>

</article>
