COM performance hints with 16550: Difference between revisions

From OS2World.Com Wiki
Jump to navigation Jump to search
Created page with "<PRE> Area Os2, Msg#1586, Sep-09-92 09:52PM From: Wilson Navarro To: All Subject: 16550 under os2 I found thi..."
 
Jugbogdan (talk | contribs)
mNo edit summary
Line 1: Line 1:
<PRE>
Article in comp.os.os2.misc: From: [[David Bolen]] (1992-09-03)
Area Os2, Msg#1586, Sep-09-92 09:52PM
  From: Wilson Navarro                     
    To: All                                 
Subject: 16550 under os2


I found this message on internet. I hope it helps someone understand com
ports under OS/2.
------------------------------------------------------------
------------
Article 11617 (102 more) in comp.os.os2.misc: From: db3l@ans.net
(David Bolen)
Subject: COM performance hints with 16550 Date: Thu, 3 Sep 1992 20:18:53 GMT
Organization: Advanced Network & Services, Inc. - Elmsford, NY Lines: 325
Organization: Advanced Network & Services, Inc. - Elmsford, NY Lines: 325


Warning: This is pretty long, but there's a summary at the end. If you just
;Warning: This is pretty long, but there's a summary at the end. If you just want to see a brief statement now:
        want to see a brief statement now:


    If you have a 16550, have a serial device that keeps DSR high while
''If you have a 16550, have a serial device that keeps DSR high while it is on (I think most modems do this by default, or are configurable), doesn't do hardware flow control, or doesn't mind getting up to 15 characters after dropping CTS and/or DSR, make sure you set BUFFER=ON when configuring your COM port with the MODE command.  With default settings, BUFFER=AUTO is really no different than BUFFER=DISABLED.
    it is on (I think most modems do this by default, or are configurable),
    doesn't do hardware flow control, or doesn't mind getting up to 15
    characters after dropping CTS and/or DSR, make sure you set BUFFER=ON
    when configuring your COM port with the MODE command.  With default
    settings, BUFFER=AUTO is really no different than BUFFER=DISABLED.


        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
I recently obtained a copy of the OS/2 physical device driver reference and was reading through the information about the async drivers (COM/VCOM.SYS).


I recently obtained a copy of the OS/2 physical device driver reference and  
From the number of posts on the subject (some from myself), it seems that a number of people are confused about what the various MODE COM settings mean, and what sort of setup was the most efficient use of COM ports when a 16550 UART was present (which seems to be universally regarded as a good idea to have in order to gain good performance). I normally use OS/2 COM programs with the RTS=HS,BUFFER=AUTO settings (as is normally recommended on the net and in the FAQ) and wondered if I was fully exploiting the capabilities of my 16550. In addition, I was still having problems with DOS environment programs (notably kermit 3.11 that just dies a horrible death) and hoped to learn a bit about how that might be improved.
was reading through the information about the async drivers (COM/VCOM.SYS).


From the number of posts on the subject (some from myself), it seems that a
After reading a bit, and performing some experimentation, I've come up with the following information and conclusions that may help other people with the 16550s. I don't place any guarantees on this information, other than that it is accurate to the best of my knowledge and seems to be backed up by my experimental results. I hope it proves helpful, or at least helps to explain the relationship between some of the MODE parameters and the use of the FIFO buffers provided by the 16550.
number of people are confused about what the various MODE COM settings mean,  
and what sort of setup was the most efficient use of COM ports when a 16550
UART was present (which seems to be universally regarded as a good idea to
have in order to gain good performance). I normally use OS/2 COM programs
with the RTS=HS,BUFFER=AUTO settings (as is normally recommended on the net
and in the FAQ) and wondered if I was fully exploiting the capabilities of my
16550.  In addition, I was still having problems with DOS environment
programs (notably kermit 3.11 that just dies a horrible death) and hoped to
learn a bit about how that might be improved.


After reading a bit, and performing some experimentation, I've come up with
(in the following, when I use the term 16550, the OS/2 drivers actually require an NS-16550A or compatible chip, and I believe the current level chips as discussed previously in the OS/2 groups are 16550AFN or 16550AF)
the following information and conclusions that may help other people with the  
16550s.  I don't place any guarantees on this information, other than that it
is accurate to the best of my knowledge and seems to be backed up by my
experimental results.  I hope it proves helpful, or at least helps to explain
the relationship between some of the MODE parameters and the use of the FIFO
buffers provided by the 16550.


(in the following, when I use the term 16550, the OS/2 drivers actually
==Introduction:==
require an NS-16550A or compatible chip, and I believe the current level
The 16550 provides for a 16-character receive hardware buffer that can be set to generate an interrupt every 1, 4, 8 or 14 characters.  It can also hold up to 16 characters in a transmit buffer, generating an interrupt only when that buffer is empty.  In other words, in its most efficient mode, the 16550 can handle transmission and receipt of data in roughly 16-byte chunks, only interrupting the CPU at the end of each chunk.
chips as discussed previously in the OS/2 groups are 16550AFN or 16550AF)


        - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Note that even if you don't make use of the extended buffering from the point of view of interrupt handling, but still receive an interrupt for every character received or transmitted, the 16550 buffer can be helpful, as it can buffer received characters if the COM handler misses an interrupt, thereby preventing receive overruns.


Introduction:
The OS/2 COM driver can fully exploit these capabilities of the 16550 depending on how it is configured.  Here's the rub though - if you take the default COM settings, and even if you use MODE to set the BUFFER parameter to AUTO, the COM driver is only partially using the capabilities of the UART. In other words, the settings that are normally posted to these groups, and are in the FAQ are not the most efficient settings.  In fact, from what I can tell, a BUFFER value of AUTO is no better than DISABLED with the other defaults for the modem signaling values.
------------
 
The 16550 provides for a 16-character receive hardware buffer that can be set
to generate an interrupt every 1, 4, 8 or 14 characters.  It can also hold up
to 16 characters in a transmit buffer, generating an interrupt only when that
buffer is empty.  In other words, in its most efficient mode, the 16550 can
handle transmission and receipt of data in roughly 16-byte chunks, only
interrupting the CPU at the end of each chunk.
 
Note that even if you don't make use of the extended buffering from the point
of view of interrupt handling, but still receive an interrupt for every
character received or transmitted, the 16550 buffer can be helpful, as it can
buffer received characters if the COM handler misses an interrupt, thereby
preventing receive overruns.
 
The OS/2 COM driver can fully exploit these capabilities of the 16550  
depending on how it is configured.  Here's the rub though - if you take the  
default COM settings, and even if you use MODE to set the BUFFER parameter to  
AUTO, the COM driver is only partially using the capabilities of the UART. In  
other words, the settings that are normally posted to these groups, and are  
in the FAQ are not the most efficient settings.  In fact, from what I can  
tell, a BUFFER value of AUTO is no better than DISABLED with the other  
defaults for the modem signaling values.
 
 
COM Driver Settings (MODE):
--------------------------
 
The extended hardware buffering mode of the async driver can be controlled
via the BUFFER parameter of the MODE command.  It can take on three values:
 
    ON        Set transmit/receive triggers to fully exploit buffering.
                (16-character transmit/receive queues for 16550).
    OFF        Set transmit/receive triggers to a single character.
    AUTO      "Automatic Protocol Override".  Adjust the transmit/receive
                triggers according to handshaking protocols in effect.


==COM Driver Settings (MODE)==
The extended hardware buffering mode of the async driver can be controlled via the BUFFER parameter of the MODE command. It can take on three values:
;ON:Set transmit/receive triggers to fully exploit buffering. (16-character transmit/receive queues for 16550).
;OFF:Set transmit/receive triggers to a single character.
;AUTO:"Automatic Protocol Override".  Adjust the transmit/receive triggers according to handshaking protocols in effect.
The "handshaking protocols" for AUTO mode use the following signals:
The "handshaking protocols" for AUTO mode use the following signals:
 
*RTS = Request To Send ( Signals FROM OS/2 COM Driver )
        RTS = Request To Send           ( Signals FROM OS/2 COM Driver )
*DTR = Data Terminal Ready
        DTR = Data Terminal Ready
*CTS = Clear To Send ( Signals TO OS/2 COM Driver )
        CTS = Clear To Send             ( Signals TO OS/2 COM Driver )
*DCD = Data Carrier Detect
        DCD = Data Carrier Detect
*DSR = Data Set Ready
        DSR = Data Set Ready
 
and refer to the following:
and refer to the following:
 
* Input Sensitivity using DSR
  * Input Sensitivity using DSR
**MODE option IDSR, default ON
        - MODE option IDSR, default ON
**If this setting is ON, then the driver will only accept data from the device while the DSR line is active.
        - If this setting is ON, then the driver will only accept data from
* Output Handshaking using CTS, DSR, DCD
          the device while the DSR line is active.
**MODE options OCTS, ODSR, default is both ON
  * Output Handshaking using CTS, DSR, DCD
**No MODE option for DCD - MODE always sets it OFF
        - MODE options OCTS, ODSR, default is both ON
**This setting controls whether CTS, DSR or DCD are used to control the flow of data to the modem.  If any of these settings are ON, the driver stops giving data to the transmit hardware as soon as the corresponding control signal drops.
        - No MODE option for DCD - MODE always sets it OFF
* RTS Control Mode
        - This setting controls whether CTS, DSR or DCD are used to control
**MODE option RTS, default is ON.  Can be one of the following:
          the flow of data to the modem.  If any of these settings are ON,
***Enabled                                              [MODE=ON]
          the driver stops giving data to the transmit hardware as soon as
***Disabled                                            [MODE=OFF]
          the corresponding control signal drops.
***Input Handshaking (RTS drops on input queue full)    [MODE=HS]
  * RTS Control Mode
***Toggling on Transmit (RTS drops unless transmitting) [MODE=TOG]
        - MODE option RTS, default is ON.  Can be one of the following:
**This setting controls how the RTS signal is controlled by the driver. If ON, DTR is used to signal when the COM port is active, while if HS, DTR is used to control the flow of data from the modem.
            + Enabled                                              [MODE=ON]
* DTR Control Mode
            + Disabled                                            [MODE=OFF]
**MODE option DTR, default is ON.  Can be one of the following:
            + Input Handshaking (RTS drops on input queue full)    [MODE=HS]
***Enabled                                              [MODE=ON]
            + Toggling on Transmit (RTS drops unless transmitting) [MODE=TOG]
***Disabled                                            [MODE=OFF]
        - This setting controls how the RTS signal is controlled by the
***Input Handshaking (DTR drops on input queue full)    [MODE=HS]
          driver. If ON, DTR is used to signal when the COM port is
**This setting controls how the DTR signal is used to control the flow of data.
          active, while if HS, DTR is used to control the flow of data
**This setting controls how the RTS signal is controlled by the driver.  If ON, DTR is used to signal when the COM port is active, while if HS, DTR is used to control the flow of data from the modem.
          from the modem.
A typical default configuration for the COM port is (ignoring some of the MODE parameters not relevant to this post):
  * DTR Control Mode
        - MODE option DTR, default is ON.  Can be one of the following:
            + Enabled                                              [MODE=ON]
            + Disabled                                            [MODE=OFF]
            + Input Handshaking (DTR drops on input queue full)    [MODE=HS]
        - This setting controls how the DTR signal is used to control
          the flow of data.
        - This setting controls how the RTS signal is controlled by the
          driver.  If ON, DTR is used to signal when the COM port is
          active, while if HS, DTR is used to control the flow of data
          from the modem.
 
A typical default configuration for the COM port is (ignoring some of the  
MODE parameters not relevant to this post):
 
         IDSR = ON              ODSR  = ON
         IDSR = ON              ODSR  = ON
         OCTS = ON              DTR    = ON
         OCTS = ON              DTR    = ON
         RTS  = ON              BUFFER = AUTO
         RTS  = ON              BUFFER = AUTO
And most suggestions for configuring the COM port for better control explicitly set RTS=HS, and BUFFER=AUTO, so I expect that many people are
running with the above settings, except with RTS=HS, allowing full hardware flow control (RTS/CTS) to the modem.


And most suggestions for configuring the COM port for better control
==Setting Interaction:==
explicitly set RTS=HS, and BUFFER=AUTO, so I expect that many people are  
For the purposes of this post (getting the most performance out of the 16550), the only settings that are really important from the above discussion are the "Extended Hardware Buffering" (BUFFER), "Input Sensitivity using DSR" (IDSR), and "Output Handshaking using CTS, DSR, DCD" (OCTS,ODSR).
running with the above settings, except with RTS=HS, allowing full hardware
flow control (RTS/CTS) to the modem.


 
Here's the basic problem.  In order to accomplish the latter two settings in their default modes, the AUTO buffering mode basically stops using the FIFO buffers. In particular, the following adjustments are "automatically" made:
Setting Interaction:
* If IDSR is enabled, then the COM driver is set up to respond to a lowering of the DSR signal within one character time.  To ensure this, the driver adjusts the receive trigger to be a single character. In other words, it lets the 16550 generate an interrupt per character. The full 16-character receive buffer is still available to prevent receive overruns, and the transmit trigger is not adjusted.
-------------------
* If either OCTS, ODSR (or ODCD - only changeable from a program) are enabled, then the device driver will respond to a lowering of the appropriate signal within a single character time.  To do this, the transmit trigger is lowered to a single character - the 16550 is set to generate a transmit interrupt for each character, although the receive trigger is not adjusted.
 
For the purposes of this post (getting the most performance out of the
16550), the only settings that are really important from the above discussion
are the "Extended Hardware Buffering" (BUFFER), "Input Sensitivity using DSR"
(IDSR), and "Output Handshaking using CTS, DSR, DCD" (OCTS,ODSR).
 
Here's the basic problem.  In order to accomplish the latter two settings in  
their default modes, the AUTO buffering mode basically stops using the FIFO  
buffers. In particular, the following adjustments are "automatically" made:
 
  * If IDSR is enabled, then the COM driver is set up to respond
    to a lowering of the DSR signal within one character time.  To ensure
    this, the driver adjusts the receive trigger to be a single character.
    In other words, it lets the 16550 generate an interrupt per character.
    The full 16-character receive buffer is still available to prevent
    receive overruns, and the transmit trigger is not adjusted.
  * If either OCTS, ODSR (or ODCD - only changeable from a program) are
    enabled, then the device driver will respond to a lowering of the
    appropriate signal within a single character time.  To do this, the
    transmit trigger is lowered to a single character - the 16550 is set
    to generate a transmit interrupt for each character, although the
    receive trigger is not adjusted.


The reason both of these automatic adjustments are made is to take the safe  
The reason both of these automatic adjustments are made is to take the safe  
Line 187: Line 82:
receive FIFO buffer on the chip helps avoid receive overruns.
receive FIFO buffer on the chip helps avoid receive overruns.


==Improving Settings==
In order to make more effective use of the 16550, you can do one of three things:
* Explicitly set the extended buffering on (MODE BUFFER=ON).
* Disable IDSR sensitivity (MODE IDSR=OFF)
* Disable any output flow control (MODE OCTS=OFF,ODSR=OFF)
Of the three, I generally prefer the former, but you may have reasons to do one of the latter two. By explicitly setting the buffering on, you will override the rules above that adjust the receive and transmit triggers. What this means is that you may receive extraneous data if DSR is actually being used to signal input and that if the modem asks the driver to stop sending data (CTS), it may still receive up to 15 more characters.


Improving Settings
I don't think either of these problems should hit most people using modems today. I believe most modems hold DSR high while they are on (or at least are configurable to do this), and most modems that handle hardware flow control (RTS/CTS) drop CTS before they are absolutely out of room. For example, the USR Courier v.32bis modem I have has a transmit buffer of 1.5K (3.25K for error control connections) and drops CTS when the buffer is 90% full (plenty of room for 15 extra characters). But of course, for a specific case the second or third choice can be made, which will make better use of the 16550 than the default settings, but not the best.
------------------
 
In order to make more effective use of the 16550, you can do one of three
things:
 
  * Explicitly set the extended buffering on (MODE BUFFER=ON).
  * Disable IDSR sensitivity (MODE IDSR=OFF)
  * Disable any output flow control (MODE OCTS=OFF,ODSR=OFF)


Of the three, I generally prefer the former, but you may have reasons to do
==Some experiments==
one of the latter two.  By explicitly setting the buffering on, you will
Just to see if any of the stuff I was learning seemed to apply, I ran some quick tests.  Nothing extremely scientific - just a couple of quick file transfers.
override the rules above that adjust the receive and transmit triggers.  What
this means is that you may receive extraneous data if DSR is actually being
used to signal input and that if the modem asks the driver to stop sending
data (CTS), it may still receive up to 15 more characters.
 
I don't think either of these problems should hit most people using modems
today.  I believe most modems hold DSR high while they are on (or at least
are configurable to do this), and most modems that handle hardware flow
control (RTS/CTS) drop CTS before they are absolutely out of room.  For
example, the USR Courier v.32bis modem I have has a transmit buffer of 1.5K
(3.25K for error control connections) and drops CTS when the buffer is 90%
full (plenty of room for 15 extra characters).  But of course, for a specific
case the second or third choice can be made, which will make better use of
the 16550 than the default settings, but not the best.
 
 
Some experiments
----------------
 
Just to see if any of the stuff I was learning seemed to apply, I ran some  
quick tests.  Nothing extremely scientific - just a couple of quick file  
transfers.
 
Using a SLIP connection (TCP/IP over a serial line), with USR v.32bis modems
on either end, I transferred a reasonably sized (115K or so) file down from a
workstation.  My COM port was set at 38.4K.  The transfer was from the
workstation back to my machine so I was mostly testing the receive
characteristics although the program used (FTP) does transmit data during the
transfer.
 
I tested using both the normal COM port settings (plus RTS=HS), and then with
BUFFER=ON rather than AUTO.  Also, I first ran the transfers without anything
else occurring on the system, and then re-ran the same transfers with a PM
monitor (one of the ones from ftp-os2 - pmload11.zoo).  The results were
interesting:


Using a SLIP connection (TCP/IP over a serial line), with USR v.32bis modems on either end, I transferred a reasonably sized (115K or so) file down from a workstation.  My COM port was set at 38.4K.  The transfer was from the workstation back to my machine so I was mostly testing the receive characteristics although the program used (FTP) does transmit data during the transfer.


I tested using both the normal COM port settings (plus RTS=HS), and then with BUFFER=ON rather than AUTO.  Also, I first ran the transfers without anything else occurring on the system, and then re-ran the same transfers with a PM monitor (one of the ones from ftp-os2 - pmload11.zoo). The results were interesting:
           FTP Transfer Time (binary mode, size = 114688 bytes)
           FTP Transfer Time (binary mode, size = 114688 bytes)
   MONITOR      BUFFER          Time (s)        Rate (cps)      Load (%)
   MONITOR      BUFFER          Time (s)        Rate (cps)      Load (%)
Line 245: Line 105:
   Yes          Auto            53              2164            98-100
   Yes          Auto            53              2164            98-100
   Yes          On              41              2797            82-86
   Yes          On              41              2797            82-86
When nothing else was running, BUFFER didn't really make much of a difference. I guess this just meant that my machine itself was fast enough to keep up with an interrupt a character in general.  I presume though (given the next set of results) that the load on the system in the On mode was much less.


When something was running (even the load program, as a PM program, takes up CPU time and interferes with running applications - I had it iconized, so it had to update the icon each second), things were very different.  In Auto mode, I got a much worse transfer time, and my system load was pretty much pegged at 100%.  In On mode, I got as good a transfer time as when nothing else was running, but at a much smaller load on the machine.


When nothing else was running, BUFFER didn't really make much of a
So I think this is pretty strong evidence that using BUFFER=ON is very different than BUFFER=AUTO when the other signaling settings are using their default values.
difference. I guess this just meant that my machine itself was fast enough to
keep up with an interrupt a character in general.  I presume though (given
the next set of results) that the load on the system in the On mode was much
less.
 
When something was running (even the load program, as a PM program, takes up
CPU time and interferes with running applications - I had it iconized, so it
had to update the icon each second), things were very different.  In Auto
mode, I got a much worse transfer time, and my system load was pretty much
pegged at 100%.  In On mode, I got as good a transfer time as when nothing
else was running, but at a much smaller load on the machine.
 
So I think this is pretty strong evidence that using BUFFER=ON is very  
different than BUFFER=AUTO when the other signaling settings are using their  
default values.
 
 
Virtual COM Driver (DOS Boxes)
------------------------------
 
After reading about VCOM (of which little is written), I don't see a magic
pill for DOS box users, other than that a BUFFER=ON setting should help lower
the CPU load and make it easier to keep the virtual interrupt rate up in the
DOS environment.
 
There was one discovery I did make however, that may help some people out.
VCOM supports two modes of accessing the COM ports - either through BIOS
calls or via virtual I/O ports.  The virtual I/O ports only emulate the lower
end INS8250 UART, and as others have noted, the virtual interrupt rate is
limited to around 1000Hz or so.
 
Since I figured it had something to do with the virtual I/O ports that was
causing the most problem with kermit, I reset kermit to use BIOS1 as its
method for accessing the COM port.  Although access through the BIOS is
technically limited to 9600 baud maximum, I was able to run kermit without a
failure, including file downloads.  When letting kermit use the virtual I/O
port, I'd generate traps at rates even as low as 2400 baud.
 
I think this behavior arises from the fact that when the application is
controlling the hardware directly, it is issuing a lot more I/O requests to
the virtual I/O port that must be handled by VCOM.  With the BIOS interface,
the application basically asks BIOS for a character, and gets them back one
at a time.  Since VCOM goes off to COM to get the character, all of the
hardware flow control and buffering used by COM is available to VCOM, and the
DOS application doesn't have to concern itself with anything.
 
So - if someone else is trying to run a COM program in a DOS box and it can
use BIOS to access the COM port rather than trying to run the hardware itself
you may be able to get it working reasonably.  At the very least, it gave me
a way to test the DOS version of kermit some of my users use from home at a
reasonable speed (although not as high as I would like) from within a DOS box.
 
 
Summary
-------


An important aspect of the support for 16550 UARTs within the OS/2 2.0 COM  
==Virtual COM Driver (DOS Boxes)==
driver is the interaction between various modem control handshaking settings
After reading about VCOM (of which little is written), I don't see a magic pill for DOS box users, other than that a BUFFER=ON setting should help lower the CPU load and make it easier to keep the virtual interrupt rate up in the DOS environment.
and the automatic control of extended buffering.  In particular, several of
the default COM port settings (IDSR=ON,OCTS=ON,ODSR=ON) when automatic
control (BUFFER=AUTO) is enabled force the driver not to use the enhanced
buffering of the 16550, and instead generate interrupts for each character
transmitted or received.  This can decrease performance and definitely places
a heavier load on the machine.


The easiest way to solve this is to use a setting of BUFFER=ON rather than
There was one discovery I did make however, that may help some people out. VCOM supports two modes of accessing the COM ports - either through BIOS calls or via virtual I/O portsThe virtual I/O ports only emulate the lower end INS8250 UART, and as others have noted, the virtual interrupt rate is limited to around 1000Hz or so.
BUFFER=AUTO, as long as it won't cause problems overrunning your modem or  
receiving extraneous information (see "Improving Settings" above).  I don't
think many users will encounter a problem if they make these changes.  From
my experiments, switching to BUFFER=ON can decrease the load on a 16MHz 386
by at least 15%, while allowing the same transfer rate on a busier system.


For the DOS Box, one hint to users trying to get reasonable performance out
Since I figured it had something to do with the virtual I/O ports that was causing the most problem with kermit, I reset kermit to use BIOS1 as its method for accessing the COM port.  Although access through the BIOS is technically limited to 9600 baud maximum, I was able to run kermit without a failure, including file downloads.  When letting kermit use the virtual I/O port, I'd generate traps at rates even as low as 2400 baud.
of DOS COM applications - BUFFER=ON may also help this situation, but if you
can live with 9600 baud, and your application supports using the BIOS
interface to the COM port, try using that modeYou may be to run the
application successfully at higher data rates through the emulated BIOS  
interface than if the application tries to use the emulated COM hardware
directly.


I think this behavior arises from the fact that when the application is controlling the hardware directly, it is issuing a lot more I/O requests to the virtual I/O port that must be handled by VCOM.  With the BIOS interface, the application basically asks BIOS for a character, and gets them back one at a time.  Since VCOM goes off to COM to get the character, all of the hardware flow control and buffering used by COM is available to VCOM, and the DOS application doesn't have to concern itself with anything.


I hope someone else finds this information useful - I know it's helped me to  
So - if someone else is trying to run a COM program in a DOS box and it can use BIOS to access the COM port rather than trying to run the hardware itself you may be able to get it working reasonably. At the very least, it gave me a way to test the DOS version of kermit some of my users use from home at a reasonable speed (although not as high as I would like) from within a DOS box.
get a better handle on how OS/2 manages the COM port, and how various
settings affect its use of the capabilities of my 16550 UARTs.


==Summary==
An important aspect of the support for 16550 UARTs within the OS/2 2.0 COM driver is the interaction between various modem control handshaking settings and the automatic control of extended buffering. In particular, several of the default COM port settings (IDSR=ON,OCTS=ON,ODSR=ON) when automatic control (BUFFER=AUTO) is enabled force the driver not to use the enhanced buffering of the 16550, and instead generate interrupts for each character transmitted or received. This can decrease performance and definitely places a heavier load on the machine.


--
The easiest way to solve this is to use a setting of BUFFER=ON rather than BUFFER=AUTO, as long as it won't cause problems overrunning your modem or receiving extraneous information (see "Improving Settings" above). I don't think many users will encounter a problem if they make these changes. From my experiments, switching to BUFFER=ON can decrease the load on a 16MHz 386 by at least 15%, while allowing the same transfer rate on a busier system.
-- David
--
/-----------------------------------------------------------------------\
\              David Bolen            \  Internet: db3l@ans.net      /
  |  Advanced Network & Services, Inc.  \  Phone: (914) 789-5327  |
/ 100 Clearbrook Road, Elmsford, NY 10523  \  Fax: (914) 789-5310    \ \----
-------------------------------------------------------------------/


For the DOS Box, one hint to users trying to get reasonable performance out of DOS COM applications - BUFFER=ON may also help this situation, but if you can live with 9600 baud, and your application supports using the BIOS interface to the COM port, try using that mode.  You may be to run the application successfully at higher data rates through the emulated BIOS interface than if the application tries to use the emulated COM hardware directly.


</PRE>
I hope someone else finds this information useful - I know it's helped me to get a better handle on how OS/2 manages the COM port, and how various settings affect its use of the capabilities of my 16550 UARTs.

Revision as of 09:47, 21 October 2018

Article in comp.os.os2.misc: From: David Bolen (1992-09-03)

Organization: Advanced Network & Services, Inc. - Elmsford, NY Lines: 325

Warning
This is pretty long, but there's a summary at the end. If you just want to see a brief statement now:

If you have a 16550, have a serial device that keeps DSR high while it is on (I think most modems do this by default, or are configurable), doesn't do hardware flow control, or doesn't mind getting up to 15 characters after dropping CTS and/or DSR, make sure you set BUFFER=ON when configuring your COM port with the MODE command. With default settings, BUFFER=AUTO is really no different than BUFFER=DISABLED.

I recently obtained a copy of the OS/2 physical device driver reference and was reading through the information about the async drivers (COM/VCOM.SYS).

From the number of posts on the subject (some from myself), it seems that a number of people are confused about what the various MODE COM settings mean, and what sort of setup was the most efficient use of COM ports when a 16550 UART was present (which seems to be universally regarded as a good idea to have in order to gain good performance). I normally use OS/2 COM programs with the RTS=HS,BUFFER=AUTO settings (as is normally recommended on the net and in the FAQ) and wondered if I was fully exploiting the capabilities of my 16550. In addition, I was still having problems with DOS environment programs (notably kermit 3.11 that just dies a horrible death) and hoped to learn a bit about how that might be improved.

After reading a bit, and performing some experimentation, I've come up with the following information and conclusions that may help other people with the 16550s. I don't place any guarantees on this information, other than that it is accurate to the best of my knowledge and seems to be backed up by my experimental results. I hope it proves helpful, or at least helps to explain the relationship between some of the MODE parameters and the use of the FIFO buffers provided by the 16550.

(in the following, when I use the term 16550, the OS/2 drivers actually require an NS-16550A or compatible chip, and I believe the current level chips as discussed previously in the OS/2 groups are 16550AFN or 16550AF)

Introduction:

The 16550 provides for a 16-character receive hardware buffer that can be set to generate an interrupt every 1, 4, 8 or 14 characters. It can also hold up to 16 characters in a transmit buffer, generating an interrupt only when that buffer is empty. In other words, in its most efficient mode, the 16550 can handle transmission and receipt of data in roughly 16-byte chunks, only interrupting the CPU at the end of each chunk.

Note that even if you don't make use of the extended buffering from the point of view of interrupt handling, but still receive an interrupt for every character received or transmitted, the 16550 buffer can be helpful, as it can buffer received characters if the COM handler misses an interrupt, thereby preventing receive overruns.

The OS/2 COM driver can fully exploit these capabilities of the 16550 depending on how it is configured. Here's the rub though - if you take the default COM settings, and even if you use MODE to set the BUFFER parameter to AUTO, the COM driver is only partially using the capabilities of the UART. In other words, the settings that are normally posted to these groups, and are in the FAQ are not the most efficient settings. In fact, from what I can tell, a BUFFER value of AUTO is no better than DISABLED with the other defaults for the modem signaling values.

COM Driver Settings (MODE)

The extended hardware buffering mode of the async driver can be controlled via the BUFFER parameter of the MODE command. It can take on three values:

ON
Set transmit/receive triggers to fully exploit buffering. (16-character transmit/receive queues for 16550).
OFF
Set transmit/receive triggers to a single character.
AUTO
"Automatic Protocol Override". Adjust the transmit/receive triggers according to handshaking protocols in effect.

The "handshaking protocols" for AUTO mode use the following signals:

  • RTS = Request To Send ( Signals FROM OS/2 COM Driver )
  • DTR = Data Terminal Ready
  • CTS = Clear To Send ( Signals TO OS/2 COM Driver )
  • DCD = Data Carrier Detect
  • DSR = Data Set Ready

and refer to the following:

  • Input Sensitivity using DSR
    • MODE option IDSR, default ON
    • If this setting is ON, then the driver will only accept data from the device while the DSR line is active.
  • Output Handshaking using CTS, DSR, DCD
    • MODE options OCTS, ODSR, default is both ON
    • No MODE option for DCD - MODE always sets it OFF
    • This setting controls whether CTS, DSR or DCD are used to control the flow of data to the modem. If any of these settings are ON, the driver stops giving data to the transmit hardware as soon as the corresponding control signal drops.
  • RTS Control Mode
    • MODE option RTS, default is ON. Can be one of the following:
      • Enabled [MODE=ON]
      • Disabled [MODE=OFF]
      • Input Handshaking (RTS drops on input queue full) [MODE=HS]
      • Toggling on Transmit (RTS drops unless transmitting) [MODE=TOG]
    • This setting controls how the RTS signal is controlled by the driver. If ON, DTR is used to signal when the COM port is active, while if HS, DTR is used to control the flow of data from the modem.
  • DTR Control Mode
    • MODE option DTR, default is ON. Can be one of the following:
      • Enabled [MODE=ON]
      • Disabled [MODE=OFF]
      • Input Handshaking (DTR drops on input queue full) [MODE=HS]
    • This setting controls how the DTR signal is used to control the flow of data.
    • This setting controls how the RTS signal is controlled by the driver. If ON, DTR is used to signal when the COM port is active, while if HS, DTR is used to control the flow of data from the modem.

A typical default configuration for the COM port is (ignoring some of the MODE parameters not relevant to this post):

       IDSR = ON               ODSR   = ON
       OCTS = ON               DTR    = ON
       RTS  = ON               BUFFER = AUTO

And most suggestions for configuring the COM port for better control explicitly set RTS=HS, and BUFFER=AUTO, so I expect that many people are running with the above settings, except with RTS=HS, allowing full hardware flow control (RTS/CTS) to the modem.

Setting Interaction:

For the purposes of this post (getting the most performance out of the 16550), the only settings that are really important from the above discussion are the "Extended Hardware Buffering" (BUFFER), "Input Sensitivity using DSR" (IDSR), and "Output Handshaking using CTS, DSR, DCD" (OCTS,ODSR).

Here's the basic problem. In order to accomplish the latter two settings in their default modes, the AUTO buffering mode basically stops using the FIFO buffers. In particular, the following adjustments are "automatically" made:

  • If IDSR is enabled, then the COM driver is set up to respond to a lowering of the DSR signal within one character time. To ensure this, the driver adjusts the receive trigger to be a single character. In other words, it lets the 16550 generate an interrupt per character. The full 16-character receive buffer is still available to prevent receive overruns, and the transmit trigger is not adjusted.
  • If either OCTS, ODSR (or ODCD - only changeable from a program) are enabled, then the device driver will respond to a lowering of the appropriate signal within a single character time. To do this, the transmit trigger is lowered to a single character - the 16550 is set to generate a transmit interrupt for each character, although the receive trigger is not adjusted.

The reason both of these automatic adjustments are made is to take the safe course, and assume that anything using those signals has been designed to assume that the signals take action within a single character time. For example, without fixing the transmit trigger, the modem could lower the CTS signal, but the 16550 might continue transmitting up to 15 characters that might still be in the FIFO transmit queue.

Of course, the problem is that with the default settings, both of these rules come into effect, and the driver ends up getting an interrupt per character for both transmitting and receiving characters. In other words, you end up using the 16550 just like any lower UART, with the single advantage that the receive FIFO buffer on the chip helps avoid receive overruns.

Improving Settings

In order to make more effective use of the 16550, you can do one of three things:

  • Explicitly set the extended buffering on (MODE BUFFER=ON).
  • Disable IDSR sensitivity (MODE IDSR=OFF)
  • Disable any output flow control (MODE OCTS=OFF,ODSR=OFF)

Of the three, I generally prefer the former, but you may have reasons to do one of the latter two. By explicitly setting the buffering on, you will override the rules above that adjust the receive and transmit triggers. What this means is that you may receive extraneous data if DSR is actually being used to signal input and that if the modem asks the driver to stop sending data (CTS), it may still receive up to 15 more characters.

I don't think either of these problems should hit most people using modems today. I believe most modems hold DSR high while they are on (or at least are configurable to do this), and most modems that handle hardware flow control (RTS/CTS) drop CTS before they are absolutely out of room. For example, the USR Courier v.32bis modem I have has a transmit buffer of 1.5K (3.25K for error control connections) and drops CTS when the buffer is 90% full (plenty of room for 15 extra characters). But of course, for a specific case the second or third choice can be made, which will make better use of the 16550 than the default settings, but not the best.

Some experiments

Just to see if any of the stuff I was learning seemed to apply, I ran some quick tests. Nothing extremely scientific - just a couple of quick file transfers.

Using a SLIP connection (TCP/IP over a serial line), with USR v.32bis modems on either end, I transferred a reasonably sized (115K or so) file down from a workstation. My COM port was set at 38.4K. The transfer was from the workstation back to my machine so I was mostly testing the receive characteristics although the program used (FTP) does transmit data during the transfer.

I tested using both the normal COM port settings (plus RTS=HS), and then with BUFFER=ON rather than AUTO. Also, I first ran the transfers without anything else occurring on the system, and then re-ran the same transfers with a PM monitor (one of the ones from ftp-os2 - pmload11.zoo). The results were interesting:

          FTP Transfer Time (binary mode, size = 114688 bytes)
  MONITOR      BUFFER          Time (s)        Rate (cps)      Load (%)
  ---------------------------------------------------------------------
  No           Auto            41              2797            N/A
  No           On              41              2797            N/A
  Yes          Auto            53              2164            98-100
  Yes          On              41              2797            82-86

When nothing else was running, BUFFER didn't really make much of a difference. I guess this just meant that my machine itself was fast enough to keep up with an interrupt a character in general. I presume though (given the next set of results) that the load on the system in the On mode was much less.

When something was running (even the load program, as a PM program, takes up CPU time and interferes with running applications - I had it iconized, so it had to update the icon each second), things were very different. In Auto mode, I got a much worse transfer time, and my system load was pretty much pegged at 100%. In On mode, I got as good a transfer time as when nothing else was running, but at a much smaller load on the machine.

So I think this is pretty strong evidence that using BUFFER=ON is very different than BUFFER=AUTO when the other signaling settings are using their default values.

Virtual COM Driver (DOS Boxes)

After reading about VCOM (of which little is written), I don't see a magic pill for DOS box users, other than that a BUFFER=ON setting should help lower the CPU load and make it easier to keep the virtual interrupt rate up in the DOS environment.

There was one discovery I did make however, that may help some people out. VCOM supports two modes of accessing the COM ports - either through BIOS calls or via virtual I/O ports. The virtual I/O ports only emulate the lower end INS8250 UART, and as others have noted, the virtual interrupt rate is limited to around 1000Hz or so.

Since I figured it had something to do with the virtual I/O ports that was causing the most problem with kermit, I reset kermit to use BIOS1 as its method for accessing the COM port. Although access through the BIOS is technically limited to 9600 baud maximum, I was able to run kermit without a failure, including file downloads. When letting kermit use the virtual I/O port, I'd generate traps at rates even as low as 2400 baud.

I think this behavior arises from the fact that when the application is controlling the hardware directly, it is issuing a lot more I/O requests to the virtual I/O port that must be handled by VCOM. With the BIOS interface, the application basically asks BIOS for a character, and gets them back one at a time. Since VCOM goes off to COM to get the character, all of the hardware flow control and buffering used by COM is available to VCOM, and the DOS application doesn't have to concern itself with anything.

So - if someone else is trying to run a COM program in a DOS box and it can use BIOS to access the COM port rather than trying to run the hardware itself you may be able to get it working reasonably. At the very least, it gave me a way to test the DOS version of kermit some of my users use from home at a reasonable speed (although not as high as I would like) from within a DOS box.

Summary

An important aspect of the support for 16550 UARTs within the OS/2 2.0 COM driver is the interaction between various modem control handshaking settings and the automatic control of extended buffering. In particular, several of the default COM port settings (IDSR=ON,OCTS=ON,ODSR=ON) when automatic control (BUFFER=AUTO) is enabled force the driver not to use the enhanced buffering of the 16550, and instead generate interrupts for each character transmitted or received. This can decrease performance and definitely places a heavier load on the machine.

The easiest way to solve this is to use a setting of BUFFER=ON rather than BUFFER=AUTO, as long as it won't cause problems overrunning your modem or receiving extraneous information (see "Improving Settings" above). I don't think many users will encounter a problem if they make these changes. From my experiments, switching to BUFFER=ON can decrease the load on a 16MHz 386 by at least 15%, while allowing the same transfer rate on a busier system.

For the DOS Box, one hint to users trying to get reasonable performance out of DOS COM applications - BUFFER=ON may also help this situation, but if you can live with 9600 baud, and your application supports using the BIOS interface to the COM port, try using that mode. You may be to run the application successfully at higher data rates through the emulated BIOS interface than if the application tries to use the emulated COM hardware directly.

I hope someone else finds this information useful - I know it's helped me to get a better handle on how OS/2 manages the COM port, and how various settings affect its use of the capabilities of my 16550 UARTs.