High Speed Modems for SCO Unix (and other modem tips)
This is an ancient post with no relevance to modern systems.
`Back in the bad old days, modems were pretty darn important.
While there are still a lot of modems in use for dial-out (to
connect to credit card processors etc.), dial-in modems on servers
are vanishing quickly.
The concept for dial-in modems is to set the modem to a fixed
DTE rate; that is, the rate which it will talk to the serial port
at, regardless of what rate it is talking to another modem at.
Three issues represented most of the modem configuration
problems on older SCO Unix systems:
Confusing the modem control and non-modem control ports
Not setting the modem and the system to fixed DTE speeds
Not understanding the relationship of getty and
SCO Unix Modem control ports are designated with an upper case
letter: /dev/tty1A is COM1 with modem control, and /dev/tty1a is
COM1 for direct connections like terminals. People would sometimes
screw up and have getty's running on both of these, which caused
confusion and unhappy results.
Setting the modem and the inittab entry to a fixed DTE speed (the speed at which it talks to the computer) was
another area of misunderstanding. Since the modem could talk to
another modem at any speed the two agreed upon, people thought they
needed cycling speeds for getty. Cycling speeds are supported, but
are not necessary or desired because the modem can be locked to a fixed DTE regardless of the speed it negotiates with another modem.. Finally, after a hangup, getty resets
the line speed to the speed indicated by anything it finds in
/usr/lib/uucp/Devices that matches the port it is on, so that speed
needs to match.
Modem configuration, whether dial-in or dial-out, used to be a
very big deal, but it got easier as modems matured. Out of the box,
more modern modems would "just work" for dial-out, and all that was
necessary for dial-in was to enable auto-answer, which you could
usually do with external dip switches. DTE speeds were preset to
57600; all you needed to do was set inittab and
/usr/lib/uucp/Devices to match.
The overall picture is this:
The tty device (lowercase version) should be owned by
You need AT LEAST a Direct entry in /usr/lib/uucp/Devices
referencing that device.
You may optionally have an ACU entry referring to the Upper
case version: if you do, put that BEFORE the Direct entry.
In either case, make sure the speed entry matches the speed you
will use in inittab.
Enable the Uppercase version in /etc/inittab at a fixed baud:
do not use a cycling baud rate.
cu to the lower case version at the speed desired and issue
whatever command is required to force the DTE rate to that
Nothing in the Operating System directly affects the answer
light on a modem. It's on if S0 is set to something other
than 0 (and in some modems, it's on providing another
condition is also met: that the port is enabled.)
Getty is awake and running only if the lower case port is
enabled, since then getty ignores the status of the DCD
(Carrier Detect) pin. That's what you want for a terminal.
For a modem, you enable the upper case port, in which
case getty sleeps until the DCD pin comes alive, which
occurs when the modem has answered the phone and there's
a carrier between the the local and remote modems. Do
not frustrate this scheme by having &C0 set in the modem,
since that causes the DCD pin to always be high, instead
of tracking the actual status of the carrier. Set &C1 &D3
Q E1 in your modem, and save that to NVRAM.
These are the details:
You do NOT want to use any of the "cycling" gettydef entries.
These are the ones that use numbers rather than letters. Their
purpose was for ancient modems that needed to match the connect
speed to the DTE speed. You simply cannot use those entries for
anything above 9600 baud (unless you force the modem to only answer
at 9600, which is silly), and you generally shouldn't use them even
for that. Bill Vermillion reminded me of that in a December 1999
post to comp.unix.sco.misc:
The bps and dce/dte match was almost universally required through
the first 2400 bps modems. However when the first 2400 bps modems
introduced error correction and compression, they needed to have
data fed at 9600bps in order to have sufficient data to compress.
So any modem that was made after about 1985 or so can and should
use a locked 9600bps interface rate (or higher), and let the
firmware in the modem handle the rest.
Even more modern modems still use compression to achieve their
magic. If your DTE rate isn't higher than the rate at which they
can deliver uncompressed data, you are just throttling throughput
for no reason. Note that 56k modems don't talk to other 56k
modems at 56k. To talk that fast, the answering modem needs to be
something special that you don't commonly buy off the shelf-it's
really an ISDN modem that (normally) only would be bought by an
ISP. Your best modem to modem speed is currently 33.6k and that
probably won't change until all phone data becomes
Beware: there are now Windows modems that seem to require
Windows software. At this moment, I don't know any way to have
these work for Unix dial-in. Also, DON'T use internal modems
Ideally, you want the DTE rate to be higher than the highest
possible connect rate, however, if you must set it lower, the modem
will use flow control.
There are some preliminaries you should take care of. However,
if this modem is simply for dial-in, you can skip quite a bit of
this for the moment, and jump directly to configuring the modem.
First, we have to determine if the serial port will support
38.4K baud. The following applies only to standard COM ports on
Intel X86 machines (tty1a, tty2a), and not to 3rd party ports
(Digiboard, Equinox, Stallion, etc.):
Further, it doesn't apply at all to any modern machines- if your
machine is only a few years old, skip this part: you won't have any
Login as root and type:
Crash responds with some info and a > prompt. You then
od sio_dma 120 | grep 3f8
You will see something like:
f01991f0: 00000000 00000000 000003f8 f015ad60
It is the last number of the second column that is important. If
this is *not* "8", your serial port will not work at 38.4K.
On Release 5, the "hwconfig" command reports "fifo=yes" on all
hardware I've seen. Unfortunately, I haven't yet seen it on a
machine old enough to have UARTS that wouldn't support 38.4K, so
I'm not certain this is giving enough information.
John Hiemenz wrote to tell me:
Regarding your article.. I have an old Cyrix48x/100 that has the
ancient 8250 UART and hwconfig still reports fifo=yes. I've got my
modem on a 3rd party card on that system.
Finally, this should not be an issue on any machine that you
should be running Unix on. If it's too old to have decent serial
ports, it's too old, period, so this really shouldn't be an issue
any more. Bela Lubkin had some comments on that:
The variable is named "sio_dma", but it has nothing to do with DMA.
What the article is crudely telling you to do is: there exists a kernel
variable, sioqueue_t sio_dma (see <sys/siohw.h>). Check whether the
bit named "SIO_HASFIFO" (value: 8) is turned on in the q_state field
corresponding to your card.
Starting with OpenServer 5.0.4, the "%serial" line prints this
information -- e.g. in 5.0.4,
%serial 0x02F8-0x02FF 3 - unit=1 type=Standard nports=1 fifo=yes
and in 5.0.7,
%serial 0x02F8-0x02FF 3 - unit=1 type=Standard nports=1 base=8 16550A/16
where the "/16" shows the FIFO size; "/1" for a FIFO-less device.
You can also look at the SIO_HASFIFO bit in scodb:
scodb:1> struct sio_queue &sio_dma
struct sio_queue size = 38 bytes
sio_dma = F0370560:
0000 0004 int q_state 00000008
The 0xC value that someone saw is equal to SIO_HASFIFO | SIO_CTS, which
means that the hardware CTS line was high when they looked at it. It
might flicker between 8 & C if the other end is actually using CTS to
flow control output from the Unix box.
Note also that Release 5 also supports higher baud rates,
including the 57600 that many modems default to for DTE. Check
/etc/gettydefs for the proper labels to use instead of "o"
to exit crash.
Should you find this is an issue nonetheless, simply
substitute 19200 everywhere you see 38400 below, and "n" everywhere
you see "o". Should you really have horrible ports, you can even
drop to 9600 ("m"). Your modems will still be able to work at 28.8
or 33.6, though they will be effectively choked down at your
Changing these kernel parameters is not at all necessary for a
simple dial-in session. You only need to do this if you plan to do
file transfers or perhaps use ppp connections. Don't bother if it's
just for dial in, character based support or application use.
You'll want to change some kernel stuff if you want to get
reliable performance out of high speed serial ports. The first is
TTHOG. This is a "choke" that effectively says that any given
driver can use up this many characters in the clist buffers. By
default, it's set to 256, which means that the serial driver can
only buffer up 256 characters at a time without processing them and
passing them on where they belong. At 38400 BPS, the serial port
could be receiving 3,840 characters per second. So if the kernel is
tied up with other chores for more than about a sixteenth of a
second, you will lose characters. Obviously, this gets worse at
even higher speeds. Increase TTHOG to a bit more than 10% of the
BPS. It makes sense for TTHOG to be a multiple of 64 because each
clist is 64 bytes, and it is clists that store the bytes controlled
by TTHOG. Increase NCLIST to approximately 120 plus TTHOG / 64.
To make these changes:
Find TTHOG and NCLIST and change them. There are several others
ways you could do this. For example, you could set TTHOG to 5824
../bin/idtune TTHOG 5824
You'll need to relink no matter how you do it:
You may also want to change the fifo array in the
/etc/conf/pack.d/sio/space.c file. At the bottom of this is a
structure that looks like this on 4.2:
This needs to be changed, but the change depends upon the serial
device being used. For tty1a (or A), it would be the very first
line. For tty2a, it would be the 9th (it's the minor number of the
device modulo 128 plus 1). What you change is the "14" in FCR_Rx14,
making it either 8, 4, or 1. This value represents how soon the
UART should interrupt the processor, thereby invoking the driver to
handle the characters. At the default setting of 14, the UART may
wait too long. On the other hand, setting it too low may be too
much for a slower system to handle. Any changes here will also
require a relink.
All commands are case sensitive and assume that you will be
connecting the modem to COM1 (/dev/tty1a). If this is not the case,
substitute where necessary (/dev/tty2a for COM2, for example).
Things you type are indended. Do not indent. Vi instructions are
in (), type what is within the ()'s, not the parentheses.
Login as root
Edit the Devices file to add this line:
Direct tty1a - 38400 direct
(or substitute 19200, or for a modern system with a modern
modem, use 57600)
It is IMPORTANT that there be no spaces or tabs before Direct,
and the line must be typed exactly with the capitalization
Note that tty1a is a LOWER CASE "a".
Note we are assuming DIAL-IN only, here. We're not adding
an ACU line, we're not running /usr/lib/uucp/make.dialer. If it's
just a dial in modem, you don't need a dialer- you can set
everything you need (which isn't much) in the modem's firmware,
save it, and forget it for a few dozen years.
While on that subject: we used to fret terribly about making the
modem "quiet"- no result codes, no echoing of commands. While this
was once necessary, it isn't anymore. With any modem worth
attaching to your serial port, you can almost always simply set it
to defaults (at&f), set the answer (ats0=1 or by dip switch if
you like) and force the DTR rate by whatever is required (see
below). For hundreds and hundreds of dial-in modems I've
configured, that's ALL you need, so what's the point of the dialer?
To reset at&fs0=1&b1 ? Unnecessary.
There are other situations where you may need finer control: modems
to be used for uucp, for example, where hardware flow control is
critical, but those don't necessarily need a dialer either- set
what you need in firmware and forget it. Why keep writing to that
flash memory every time a call hangs up?
If, however, the modem is going to be used for dialout, then you
need the dialer: first for the obvious reason that dialing out is
what it does, and secondly to reset things back to the state you
want when the call is done. Finally, if the modem is
super-critical, located in a non-accessible location, you may want
the reset capability just in the rare case that something gets
changed by the incoming call. That's rare, and the simple solution
is just to shut the modem on and off, but you can do the dialer bit
if you want- I don't.
Tom Parsons thinks you should use the dialer anyway, even if it's
just a simple ATZ entry. In a newsgroup posting, Tom
Make this the first entry for tty2A in /usr/lib/uucp/Devices:
ACU tty2A - 57600 /usr/lib/uucp/atdial57
Now create the file, /etc/default/atdial57 and in it put just this one line.
Then create /usr/lib/uucp/atdial57 with
# ln -s /opt/K/SCO/Unix/5.0.5Eb/usr/lib/uucp/atdialer /usr/lib/uucp/atdial57
Tom's reasoning is that you need that for getty to cycle back to
the right baud rate. I've actually tested this with only a Direct
entry, and found that getty will read its baud from that, so I
still feel the ACU line is unnecessary. However, it certainly won't
hurt anything, so I see nothing wrong with doing this if it makes
you feel better.
There's another reason to do that though: the ATZ throws
the modem back to the defaults you have stored in firmware. Many
modems can be set to do that upon carrier loss, which again would
make the ACU unnecessary if all you need is dial-in.
&c1&d3&s0=1 is typical.
For either or both of these commands, you may get "Already
disabled". That's OK. It's not really necessary to disable tty1A
but we want to start from a known point here.
chown uucp /dev/tty1a
Note that's a lower-case "a". Type:
cu -ltty1a dir
You should get a CONNECTED message if your modem is connected
properly and turned on. Type some of the following:
AT&F (Fetch factory configuration)
ATE1 (set to echo commands)
ATQ0 (Response codes)
ATS0=1 (Set to answer after 1 ring-that's a zero after the S)
AT&B1 (Set DTE to baud rate currently connected at: Hayes, USR)
AT$SB19200 (Set DTE to 19200 for Multitech)
AT&N0 (Some Hayes use this to specify "connect at any speed")
AT&W (Write NonVolatile Registers)
AT&W0 (Write Register set 0- Multitech, some Hayes)
~. (Disconnect from cu)
The most important things are ATS0=1 and to set the DTE rate
(usually AT&B1 for Hayes, UsRobotics and compatibles).
to disconnect. That's a tilde followed by a period.
Find the line that looks like:
Se1A:2:off:/etc/getty -t60 tty1A 6
Note we're changing the line with the UPPER CASE "A".
The number after tty1A may be different or may be a lower case
Change the line to look like:
Se1A:2:off:/etc/getty -t60 tty1A ox
(or if 19200, use nx instead of ox, and if using 57600, use
Make the same change in /etc/conf/init.d/sio
"sio" is one of the component files that are used to rebuild
inittab when you "rebuild the kernel environment" after a relink.
It is important to change this here, or your effort will be lost
after a relink.
Note that third-party serial cards will have a different file in
/etc/conf/init.d. A Digiboard, for example, would have the file
Do not copy these files to .baks or .olds: if you do, the
environment rebuild will simply concatenate ALL the files in
/etc/conf/init.d, and your inittab will have duplicate and possibly
Edit the file /etc/gettydefs. Again, this is an area where you
don't necessarily need to change anything. For simple use, you can
leave gettydefs as it is.
n # B19200 HUPCL # B19200 CS8 SANE HUPCL IXANY TAB3 #\r\n@!login: # n
o # B38400 HUPCL # B38400 CS8 SANE HUPCL IXANY TAB3 #\r\n@!login: # o
Copy one of the above lines and change it to read:
Have someone test the modem dial-in. If they get garbage, it may
be because your serial port cannot support 38.4K
Try 19200. Repeat the above procedure, but the line in Devices
Direct tty1a - 19200 direct
and the line in inittab will read:
Se1A:2:off:/etc/getty -t60 tty1A n
It is possible to have serial ports that simply will not support
more than 9600 baud.
Once this is working, you need to
Find the line that has tty1A in it and change it so that it
looks exactly like the same line in /etc/inittab. Then write the
file (:wq), and you are done.
Brian points out that 115200 is possible on newer systems:
From: [email protected]
Subject: Re: Configuring speed for SCO OpenServer
Date: 30 Mar 2005 16:31:29 -0800
Message-ID: <[email protected]>
Content-Type: text/plain; charset="iso-8859-1"
X-Trace: posting.google.com 1112229094 2492 127.0.0.1 (31 Mar 2005 00:31:34 GMT)
X-Complaints-To: [email protected]
NNTP-Posting-Date: Thu, 31 Mar 2005 00:31:34 +0000 (UTC)
In-Reply-To: <[email protected]>
Complaints-To: [email protected]
Injection-Info: f14g2000cwb.googlegroups.com; posting-host=188.8.131.52;
Xref: number1.nntp.dca.giganews.com comp.unix.sco.misc:165678
Actually, you can use 115,200 and I actually use that same article on
Tony's site as my recipe for doing it, just adding another line "q" to
gettydefs and using 115200 in place of 57600 everywhere.
I set that up for dial-in or ppp (in/out) modems on the theory that I
need the host-modem interface to be faster than 56k in order to get any
value out of the modems on the fly compression.
I avoid doing it on built-in com ports though as you'll be generating
more interrupts. I usually do it on various digi and equinox smart
serial cards and networked serial port server boxes.
Even on built-in ports though, it's probably not noticeable on lightly
loaded systems 5 years old or newer.
My gettydefs ends with:
qx # B115200 HUPCL # B115200 CS8 SANE HUPCL TAB3 RTSFLOW CTSFLOW
-ORTSFL #\r\nlogin: # qx
qz # B115200 HUPCL # B115200 CS8 SANE HUPCL TAB3 -IXON -IXOFF -IXANY
RTSFLOW CTSFLOW -ORTSFL #\r\nlogin: # qz
(I use qx, qz is just there for "might want xon/xoff some time")
my Devices includes:
ACU tty01E4 - 115200 /usr/lib/uucp/atdial115
atdial115 is a symlink to atdialer and /usr/lib/uucp/default/atdial115
works great on at least 5.0.6 and 5.0.7.
5.0.5 & lower?
I don't remember if it works on 5.0.5 without a 3rd party dialer. I
think the stock atdialer binary on 5.0.5 doesn't accept 115200 as a
valid value, although the serial driver has no problem with it. I do
know that it works with at last 2 3rd party dialer binaries if not the
I also know it works with the stock atdialer if you are using a smart
serial card that provides false speeds just for this purpose. You use
110 or one of the other extremely low but valid values, and atdialer
accepts it, and the serial driver really does 115k when asked to do 110
if the feature is enabled in the driver.
Seems to me it should be possible to set it up so that the modem &
serial driver do 115k but the modem simply doesn't report it's
connection speed and atdialer doesn't look for it, but merely looks for
"CONNECTED" and so the stock 5.0.5 & under atdialer could maybe work
that way too. But I don't think I ever tried it.
The other possible limiting factor is can the modem do 115k to the host
and in this case it's known yes, and a strong probably yes for any
other 56k modem too.