Cover V03, I02
Figure 1
Sidebar 1
Sidebar 2
Table 1


Multiport Serial Installation

Larry Reznick

When you have no more than five or ten users making only occasional demands on your UNIX system, a LAN is overkill. Recently I setup a UNIX system for a small classroom. The maximum system load of eight students typing at once but for short periods was extremely light. It was more cost-effective for me to install a multiport serial board and eight inexpensive terminals than to string a local area network.

A good multiport serial board with terminals set within 100 feet of the system and running at 9600 or 19200 BPS was sufficient. I selected the DigiBoard DigiCHANNEL PC/8, which has eight ports. (There are also 4-port and 16-port versions.) The board plugs into an ISA slot. A 78-pin plug connects into the back of the board. The board allows either an octopus cable or an 8-connector box. In my case the octopus cable was too short to string directly to the terminals, so since I had to provide cables to the terminals anyway, I ordered the box. Serial cables extended from the box to the eight terminals. The terminals could just as easily be modems if you need to hook up a multiline modem control. Check with the DigiBoard company for the appropriate board type if you're controlling modems. The higher speed modems may require a different board than the one I used for terminals.)

I needed null-modem cables to connect to the terminals. I had a bunch of well-shielded cable, so I built my own using only five wires: 2 and 3 crossed, 8 and 20 crossed, 7 straight to 7. See Figure 1 for a diagram of this cable. Pins 2 and 3 are the standard TRANSMIT crossed to RECEIVE. Pin 7 is the standard GROUND. Pin 8, CARRIER DETECT, is crossed to 20, DATA TERMINAL READY (DTR), to indicate that a carrier is present. (Note that modems would require a different cable configuration.)

On the PC/8 board are eight I/O port DIP switches, one status register DIP switch, six interrupt request (IRQ) address selection jumpers, eight odd/even IRQ jumpers, and two board ID jumpers. I/O port and status register DIP switches let you select the hexadecimal port addresses used to talk with the devices. However, these addresses are standardized and documented within the manuals supplied with the board. The trick is to find addresses that aren't already being used by other devices in the system. You must also pick an IRQ that avoids conflicts with other devices. The odd/even IRQ jumpers tell whether the IRQ address used should be the odd or the even address in the group. Because you can install multiple boards, each board has ID jumpers to mark which board is which. (This is similar to each SCSI device having its own address.)

How to Find Ports and IRQs

Device driver configurations rest in the /etc/conf tree. In /etc/conf/bin you'll find several programs for working with installable devices, hence the program names all begin with "id." A sidebar, "Installable Device Programs," briefly explains these. The remaining entries in /etc/conf are directories. Another sidebar briefly explains these directories.

In my experience with UNIX systems I have never found a portable program that queries device address settings. So, the only way I know to find out where the conflicts are between an existing driver and any new driver is by examining the mdevice and sdevice files. The sdevice file contains the device name in field 1, whether to put the driver in the kernel in field 2, the interrupt vector number (IRQ) in field 6, and the starting and ending I/O addresses in fields 7 and 8. Many devices have no address settings (0 in fields 6, 7, and 8) or aren't used (N in field 2). You can use a simple one-liner to reduce the list to just those with address settings:

cut -f1-2,6-8 /etc/conf/cf.d/sdevice | egrep -v '0     0       0'

Between each zero in the egrep argument is a single tab. This isolates the five fields needed to choose IRQ and I/O addresses. Any unused device with an address will have an N in field 2. Table 1 shows a sample output from my Esix system.

You can set the DigiBoard to use any IRQ from 2 to 7. Table 1 showed me that IRQ 2 and IRQ 5 were available. IRQ 2 was set to off, but was set aside for the third asy port (address 0x3e8). I didn't have a third communications device in the system but I thought it might be better to reserve IRQ 2. IRQ 5 was reserved for a device named rmc. I couldn't find any documentation for what an rmc device is -- comments in the /etc/conf/pack.d/rmc/stubs.c file weren't revealing -- so I used IRQ 5 for the DigiBoard.

The DigiBoard's available I/O addresses depend on whether you're using a 4-port, 8-port, or 16-port board. The 8-port board offered six hex address ranges: 100-140, 148-188, 1C0-200, 210-250, 258-298, and 2C0-300. I referred again to the list in Table 1 and excluded the 100 and 148 ranges because of f2ha's use of 140 to 14f. The 1c0 range was out because the dk device used 1f0 to 1ff. The 210 range was available because rmc was disabled. I could use the 258 range because the third lp (address 0x278) was disabled but, if I ever wanted to add a third printer, this would haunt me. The 2c0 range was used by the second asy (address 2f8) and I definitely wanted to save that, so only one range was available: 210-250, the same range freed up by the rmc device.

Armed with the IRQ and I/O addresses, I changed the jumper shunts and DIP switches on the DigiBoard to correspond. I then plugged the board into the slot, closed the box, and booted the system.

Making the Device Nodes

Once I had logged in as root, it was time to create the new serial device nodes. On other systems, I've gone into the device's subdirectory within /etc/conf/pack.d and used

idinstall -g -s devicename >System

This extracts the current entries from the sdevice file for the named device. Then, I can edit my copy of the file and reinstall it with

idinstall -u -s devicename

using a -k flag if I want to keep my copy of the file around until I'm done testing.

I may also need to change the eighth field in mdevice, which holds the maximum number of ports allowed for this device. Unfortunately, you can't get the mdevice entry with idinstall, and changing mdevice can sometimes require a complicated series of steps.

Fortunately, Esix has a special script named initasy that will create the new serial device nodes.

The initasy script already has a provision for the DigiBoard PC/8. Unfortunately, Esix developed that part of the script expecting the DigiBoard to be the only provider of serial ports. I already had two serial ports and really wanted to keep them. (One port had a modem and the other was reserved for the future.)

Esix's initasy script offers an "Others" selection. This selection allows up to 16 serial ports. When initasy prompted me for the number of ports, I told it 10. It prompted for the base I/O address, the IRQ, the modem control register, and the status port address of each port. For the first two, I gave the numbers for my two existing serial ports. (Those values came straight out of the sdevice file except that as per initasy documentation I input OUT2 for all register prompts. For the remaining eight ports, the DigiBoard's ports, I gave the IRQ and I/O addresses I'd already selected. The status port address is identical for all I/O addresses, 0x250.

initasy rewrites the space.c file and other device driver files in the other /etc/conf directories. When the script is almost done, it rebuilds the kernel. Part of rebuilding the kernel is setting up the /etc/inittab file. You'll need to check that file. It should have entries for the DigiBoard's ports. In my system, tty02 through tty09 were setup along with the tty00 and tty01 for my existing serial ports. I have seen some versions of UNIX duplicate the entries in inittab. If there are duplicates, you should delete all but one set then change to cause a respawn, save the inittab file, and reboot the system.

Because nobody else was on the system, I found it far simpler to reboot to start the new serial devices than to use init -q. The init -q command forces init(1M) to reread the inittab. Unfortunately, that adds new entries but doesn't kill or change existing entries already loaded in the process list. If you run ps, you may find entries for previously activated ttys. After fixing the inittab for those entries, you would then have to kill the active tty gettys. init knows to respawn them with their newest settings because of the init -q.

Once the system was rebooted, I checked the terminals for their gettys. All eight of them were working. With this configuration, the system could support eight students typing away, someone working multiple logins on the console using virtual terminals, and UUCP waking up from time to time to use the modem. This was a great solution for my classes and would work for other low-demand terminal accesses.

About the Author

Larry Reznick has been programming professionally since 1978. He is currently working on systems programming in UNIX, MS-DOS, and OS/2. He teaches C language courses at American River College in Sacramento. He can be reached via email at: rezbook!