- "Printer Networking with TurboDOS"
  Tedd Kurts, MuSYS Corporation
  "Microsystems", Vol.5, No.10, October 1984, p.106
(Retyped by Emmanuel ROCHE.)

In working with TurboDOS users on a daily basis, I have observed many of  them
attempting  printer configurations, only to find their  efforts  unsuccessful.
The  problem  appears  to stem from a lack of  understanding  of  the  printer
networking concepts involved. This article will outline the steps necessary to
configure a TurboDOS operating system with one or more printers.
There  is  a  radical difference between CP/M or MP/M  operating  systems  and 
TurboDOS.  No printer drivers (or only skeletal examples) are supplied with  a
CP/M  or MP/M as purchased from Digital Research,Inc. The user must write  his
own drivers, and integrate them into the I/O section of the operating  system;
he  must,  therefore,  be  a  competent  assembly  language  programmer,   and
understand  the  workings  of the CP/M BIOS or MP/M XIOS. (ROCHE>  I  had  the
curiosity  of searching for "Printer" in the Index of "The  CP/M  Programmer's
Handbook",  by  Andy Johnson-Laird, Osborne/McGraw-Hill, 1983, the  only  book
ever  written  on  the subject of writing a BIOS for CP/M. There  are  only  3
entries:  "Printer echo", "Printer errors", and "Printer timeout error".  This
is  because  printers are, fundamentally, outside  the  microcomputer  running
CP/M.  Hence,  only CP/M programs dealing with printers (like  WordStar)  have
(their own) printer drivers.)
TurboDOS,  on the other hand, comes with several printer drivers  for  various 
methods  of handshaking; these are assembled in Microsoft RELocatable  format,
and need only be linked to the body of the TurboDOS operating system by  means
of  the  GEN  (system generation) utility (also supplied).  For  fine  tuning,
PARameter  files can be created or modified with a simple text  editor.  Thus,
the  person  who  "generates" a bootable TurboDOS operating  system  from  the
modules  supplied  in  Microsoft REL form need not  be  an  assembly  language
programmer  (ROCHE>  ??? How many end users are familiar  with  Microsoft  REL
files  and  linkers?), though he must understand what  functions  the  printer
drivers and PARameter files perform, and how to modify them to suit his needs.
(ROCHE>  Isn't  it  the  job of the  "System  Implementer"  to  port/implement
TurboDOS on a particular hardware, so that the user can use the software?)
The procedure falls into the following steps:
      - Determine the handshaking required by your printer(s), and select  the 
        appropriate driver module(s).
      - Determine  the baud rate to be used, and create a corresponding  patch 
        in a PARameter file.
      - Assign the printer to a spooling queue by a patch in a PARameter file.
Exampes will be given, showing exactly how to perform theses steps.

1) Printer handshaking and cabling
To  determine  what handshaking protocol should be  used  (and,  consequently, 
which printer driver module to select), consult your printer manual. The  most
commonly-used  methods are hardware handshake (sometimes called CTS (Clear  To
Send)  protocol);  XON/XOFF protocol; ETX/ACK protocol; or  a  combination  of
hardware handshake and one of the other two (ROCHE> Software handshakes.). All
of  these  can  be  used with serial printers;  a  special  form  of  hardware
handshake,  standardized  by  Centronics,  is  generally  used  for   parallel
When  hardware  handshaking  is used on an RS-232-C  serial  channel,  only  3 
conductors  are required: the data line (from computer to printer); a  control
signal line; and the signal ground line. The printer accepts characters  until
its  buffer  is  about 3/4 full; it then turns off  the  control  signal.  The
computer  must  be  able to detect this signal, and stop  sending,  until  the
printer  turns  the  signal on again, when the buffer  is  nearly  empty.  The
control signal chosen is usually DTR (Data Terminal Ready, pin 20 of the  1969
RS-232-C  standard)  or RTS (Request To Send, pin 4), but  some  printers  use
other signals. This is the industry-preferred protocol, for several reasons:
     1) only one data channel is needed;
     2) it  is a hardware handshake and, therefore, the driver is  simple  and 
        takes less CPU time;
     3) a  cable  disconnection during printing does not cause loss  of  data. 
        When the cable is reconnected, printing picks up where it left off.
When  XON/XOFF  protocol  is  used, 2 data channels  are  required:  one  from 
computer  to printer, the other from printer to computer. The printer  accepts
characters  until  its  buffer is nearly full, and then sends  the  XOFF  code
(Transmit OFF, or "pause transmission", ASCII DC3, Control-S, 13H) to tell the
computer to stop sending; when the printer is ready to accept more characters,
it  sends  the  XON code (Transmit ON, or "resume  transmission",  ASCII  DC1,
Control-Q, 11H).
When  ETX/ACK  protocol is used, 2 channels are again required.  The  computer 
sends  a fixed number of characters to the printer (amounting to about 75%  of
the  buffer capacity) followed by an ASCII ETX (End-of-TeXt,  Control-C,  03H)
character; it then waits until it receives an ASCII ACK (ACKnowledge, Control-
F, 06H) character from the printer.
Both XON/XOFF and ETX/ACK can lose data in the event of a cable disconnection. 
For this reason, they are sometimes combined with a hardware handshake.
If the printer can use more than one of these protocols, selection is done  by 
setting switches or placing jumpers on the circuit board.
Care must be taken to see that the cable connects the correct pins of the  RS-
232-C connectors at each end. Devices designated DTE (Data Terminal Equipment)
send  data  on  pin 2 and receive it on pin 3; devices  designated  DCE  (Data
Communications Equipment) receive on pin 2 and send on pin 3. Thus, the  cable
connecting  a  DTE  device  to a DCE  device  has  corresponding  pin  numbers
connected.  If, however, both devices are DTE or both are DCE, then the  cable
connecting them must have pins 2 and 3 at one end connected to pins 3 and 2 at
the other. Also, if the control signal appears on (say) pin 14 at the  printer
but is required on pin 20 at the computer end, the cable must have this cross-
connection also.

Printer drivers
For  each  of  the protocols described above,  TurboDOS  has  a  corresponding 
driver.  The  most  common  ones  are  designated  LSTCTS.REL  (CTS   hardware
handshaking);  LSTXON.REL (XON/XOFF protocol); LSTETX.REL (ETX/ACK  protocol);
and LSTCEN.REL (a Centronics parallel printer driver used mainly in  Televideo
implementations).  Less  common  are LSTPAR.REL, the  driver  for  a  standard
Centronics  parallel printer; and LST300.REL, a simple, slow-speed,  Teletype-
like  serial driver. This has no provision for error detection, and relies  on
the  printer being able to keep up with the transmission rate. One or more  of
these drivers is placed in the GEN file of the appropriate server or satellite
processor  when  the GEN (system generation) program is run  to  generate  the
TurboDOS operating system.

2) Setting printer baud rates  (BR)
After determining handshaking and selecting the appropriate driver module, the 
baud rate should be checked against the default value for that driver. If some
rate  other  than  the default is desired, use a text  editor  to  modify  the
appropriate  patch  point  in the PARameter file  containing  global  symbolic
patches  for the node. Examples of symbolic patch points are shown in  Listing

Listing 1
        Baud Rate patch point (PAR)  Printer driver (GEN)
        ---------------------------  --------------------
        CTSBR = hn ln   Default=6E           LSTCTS
        XONBR = hn ln   Default=07           LSTXON
        ETXBR = hn ln   Default=07           LSTETX
where  hn represents the high-order 'nibble' (4 bits), which can have  only  3 
valid values in these particular patch points:
     0  Represents the disabling of all hardware handshaking.
     4  Represents hardware handshaking.
        Bit 6 is set, and enables CTS.
        Is used with XONBR and ETXBR drivers to enable the respective protocol
        + CTS.
     6  Represents hardware handshaking for output only (input disabled).
        Is used for all CTSBR patch points.
and  ln  represents  the  low-order nibble, which can  have  16  valid  values 
representing the 16 baud rate values. The most common are:
        5 = 300
        7 = 1200
        E = 9600
Example: CTSBR = 6E     ;CTS handshaking at 9600 baud
         XONBR = 47     ;XON/XOFF + CTS handshaking at 1200 baud
         XONBR = 07     ;XON/XOFF handshaking at 1200 baud
         ETXBR = 05     ;ETX/ACK handshaking at 300 baud

Print spooling
The  2  print  modes  are  either  spooled  or  direct.  In  most   multi-user 
applications,  spooled  printing  is preferred over direct.  When  a  file  is
spooled,  TurboDOS  creates a print file on the disk. When the  print  job  is
done, TurboDOS will queue the print files for de-spooling in a first-in first-
out (FIFO) manner. Print file de-spooling is a background process that is done
The  De-SPool Printer Assignment Table (DSPPAT), in the module LSTTBL,  is  an 
array  of 16 bytes (for printer A-P) that defines the queue assigned  to  each
printer.  Positions  1  through 16 in the array correspond  to  printers  A-P,
respectively.  The hex value (01-10, corresponding to printers A-P)  found  at
each  position  in  the  array defines the queue  to  which  that  printer  is
assigned.  A value of 00H indicates that the printer is off-line. The  default
value (01H) assigns all printers to queue A. A de-spool assignment table looks
like this:
DSPPAT = 01,01,02,02    ;Printer A to Queue A,
                        ;printer B to Queue A,
                        ;printer C to Queue B,
                        ;printer D to Queue B, etc.
The  files created by the spooler default to the system drive. To  change  the 
default, you may patch the symbol SPLDRV in the module LCLTBL, as follows:
SPLDRV = 0FFH   ;0FFH is default for system drive.
                ;Hex value of 0-F specify spool drive of A-P.
The print mode for a local user is determined by the symbol PRTMOD, located in 
module LCLTBL. The default value is 1, which specifies spooling. To change the
default, patch PRTMOD as follows:
PRTMOD = 1      ;1 is default for spooling.
                ;Hex value of 0 for direct printing,
                ;and 2 for print to console.

Print queues
A  print  queue  is  a list of print  jobs  awaiting  de-spooling.  The  QUEue 
ASsignment  Table (QUEAST) defines which queues of A-P are local,  remote,  or
invalid. Also specified are the network addresses for each remote queue.
QUEAST = 00,(0000)      ;Queue A local   -- First 3 bytes zero
         0FF,(0000)     ;Queue B invalid -- First byte 0FFH
The  patch symbol QUEPTR in module LCLTBL specifies initial queue  or  printer 
assignments.  If  print  mode  is  spooled,  this  symbol  specifies  a  queue
assignment.  If  print  mode  is  direct,  this  symbol  specifies  a  printer
QUEPTR = 1      ;1 is default.
                ;Hex values of 01-10 represent assignments of A-P.
                ;Zero signifies no queue, or printer off-line.

3) Printer assignment
There  are 2 classes of printers in a TurboDOS network: local and remote.  The 
PrinTeR  ASsignment Table (PRTAST) contains, for each local or remote  printer
in  the  system, one byte specifying the printer, and 2 bytes  in  parentheses
specifying  the node address of the printer. In the printer designation  byte,
the  high-order nibble can only have 2 values: 0, signifying a  local  printer
physically attached to the node; or 8, signifying a remote printer attached to
some  other  node. The low-order nibble specifies the printer  number  (0-0FH,
corresponding to printers A-P). The following is an example of an entry:
        PTRAST = 00,LSTDRA,0FF,(0000),01,LSTDRA,85,(0002)
        00,LSTDRA  -- Local printer A to channel 0
        0FF,(0000) -- Printer B is invalid
        01,LSTDRA  -- Local printer C to channel 1
        85,(0002)  -- Printer D is printer F on Remote node 2.
In  looking  at the first bytes (00, 0FF, and 01), we find  2  Local  printers 
attached  to this node, and one Remote (85). The high-order nibbles (0 and  8)
indicate  Local  and  Remote printers,  respectively.  The  low-order  nibbles
indicate  that  Printer  A is attached to channel 0 (first  serial  port)  and
Printer C is attached to channel 1 (second serial port).

Local printer configurations
Any  node  (whether  server or a satellite) can be configured  for  up  to  16 
printers, designated A-P. These printers can all be in use simultaneously, and
have  other  print jobs waiting in the queue. Before attempting to  work  with
full networking, we will look at local printer configurations.

Listing 2
NODE.GEN  ;TurboDOS operating system GENeration file
LSTPAR          ;Printer driver for Parallel (Centronics) interface
LSTCTS          ;Printer driver for CTS hardware handshake
LSTETX          ;Printer driver for ETX/ACK software handshake
DSPOOL          ;Despooler for Local printer (only goes in satellites)

NODE.PAR  ;TurboDOS operating system PAR(ameter) file
CONAST = 00,CONDRA              ;First serial channel -- Console terminal
PTRAST = 00,LSTDRA              ;Parallel port -- No serial channel used
         01,LSTDRB              ;Second serial channel -- Second printer driver
         02,LSTDRC              ;Third serial channel  -- Third printer driver
DSPPAT = 00,01,02               ;No queue (Direct)
                                ;Second printer Queue A
                                ;Third printer Queue B
QUEAST = 00,(0000),00,(0000)    ;Queues A and B are Local queues
CTSBR = 6E                      ;CTS with handshake at 9600 baud
XONBR = 07                      ;XON without handshake at 1200 baud
        Figure  1. Local printer configuration with parallel CTS and  XON/XOFF 
The example shown in Listing 2 has 3 printers on a node. The first printer  is 
Direct,  and  uses a parallel interface. The second printer is  Spooled,  with
hardware  handshaking  at  9600  baud. The third printer  is  Direct,  with  a
software  handshake  at 1200 baud. See Figure 1. Note that the  assignment  of
LSTDRA is a 2-byte value assigning a Local printer to the first printer driver
in  the  GEN file. The assignment of LSTDRB is for a Local printer  using  the
second printer driver in the GEN file, etc.
Note  that  the  parallel driver (LSTPAR) does not use a  serial  channel  for 
communication  with  the printer, and this must be explicitly  stated  in  the
PTRAST entry. Note, too, that the positions of the printer drivers in the  GEN
file  directly correlate to how printers are assigned in the table.  The  last
letter of LSTDR? tells the printer assignment table which driver to use in the
GEN -- i.e., LSTDR(A) uses the first printer driver in the GEN, LSTDR(B)  uses
the second printer driver, and LSTDR(C) uses the third printer driver.

Listing 3
NODE.GEN  ;TurboDOS operating system GENeration file
LSTCTS          ;Printer driver for CTS hardware handshake
LSTETX          ;Printer driver for ETX/ACK software handshake
LSTXON          ;Printer driver for XON/XOFF software handshake
DSPOOL          ;Despooler for Local printer (only goes in satellites)

NODE.PAR  ;TurboDOS operating system PARameter file
CONAST = 00,CONDRA              ;First  channel -- Console terminal
PTRAST = 01,LSTDRB              ;Second channel -- Second printer driver
         02,LSTDRC              ;Third  channel -- Third printer driver
         03,LSTDRA              ;Fourth channel -- First printer driver
DSPPAT = 01,02,03               ;Printer A to Queue A, B to B, etc.
QUEAST = 00,(0000),00,(0000)    ;All Queues valid and Local
CTSBR = 6E                      ;CTS printer at 9600 baud
ETXBR = 0C                      ;ETX/ACK at 4800 baud
XONBR = 67                      ;XON/XOFF + CTS by setting high-order
                                ;nibble to 6, at 1200 baud.
        Figure 2. Local printer configuration with ETX/ACK, XON/XOFF plus  CTS 
        and high-speed CTS
The  example given in Listing 3 shows 3 printers on a single node.  The  first 
printer  is  Spooled, with software handshaking (ETX/ACK) at  4800  baud.  The
second  printer  is  Spooled,  with both a  software  and  hardware  handshake
(XON/XOFF and CTS) at 1200 baud. The third printer is Spooled, with a hardware
handshake at 9600 baud. See Figure 2.

Printer networking
TurboDOS, by its nature, is a networking operating system that networks via  a 
distributed   processing  architecture.  A  TurboDOS  circuit  is  a   network
communication  path between individual processor nodes. In a  single  computer
system, there is a simple and closely-coupled connection between the nodes. An
area  of  confusion to TurboDOS users is printer networking, partly due  to  a
lack  of detailed documentation. Listing 4 comprises some examples  that  will
illustrate networking applications.

Listing 4
PTRAST = 00,LSTDRA,81,(0001)
00  is  one byte consisting of a high-order nibble (Local=0, Remote=8)  and  a 
low-order  nibble  (Local=port or channel number, Remote=printer  A-P  in  Hex
values of 0-F).
LSTDRA  is a 2-byte assignment entry (global symbolic address of driver  entry 
point) for Local printers, in which the last substitution character points  to
the printer driver to use in the GEN file, e.g., A = First Driver, B = Second,
C = Third.
81 is a Remote printer, which is Printer B in Remote's PTRAST.
(0001) is the Remote assignment entry in which the first byte of 00 refers  to 
the  circuit,  and the second byte of 01 refers to the node  on  that  circuit
(Circuit 00 = server, Node 01 = First satellite).
For  a remote printer, the first byte must have the Sign bit set. To  set  the 
Sign  bit, the high-order nibble of the first byte must have the Hex value  of
8.  This  lets the Local Node know that this is a Remote printer, and  is  not
physically  attached.  The low-order nibble of the first  byte  specifies  the
printer  letter to be accessed on the Remote processor. The  'word'  following
the  first  byte  specifies  the network  address  of  the  Remote  processor,
consisting of a Circuit and a Node. When referring to hardware, a word for  an
8-bit processor is 8 bits and, for a 16-bit processor, is 16 bits.
When  referring  to words in TurboDOS (on both 8- and  16-bit  processors),  a 
single  word is 2 bytes or 16 bits. A word is specified in the PARameter  file
whenever  a  Hex  value  greater than 255 is entered, or  when  the  value  is
surrounded by parentheses.
Another printer assignment might be written this way:
PTRAST = 00,LSTDRA,0FF,(0000),01,LSTDRA,83,(0001),84,(0001)
This  assignment defines 2 printers physically attached to a Remote  satellite 
node.  Setting  the high-order nibble of the first byte to 8 tells  the  Local
node (server) that 2 other printers are Remote. The Local node (server) "sees"
them  as printers D and E, corresponding to the order of the printers  in  the
assignment  table. The low-order nibbles of the first bytes, with values of  3
and  4, respectively, tell the Local system to look to the printer  assignment
table  of the Remote node for D and E. The 2-byte entry (Circuit 00, Node  01)
tells  the Local processor that the Remote printers are attached to Node 1  of
the network (satellite 1).
Printer assignment of Remote node (satellite 1) would look like this:
This assignment shows a 9-byte offset resulting from 3 printers being assigned 
to the system defaults on Node 0. Each printer on Node 0 (A, B, C) takes up  a
3-byte  entry;  thus, 3 bytes * 3 system printers = 9 byte  offset  in  Remote
PTRAST. Printer D is Local, and physically attached to serial channel 1, while
printer E is Local and physically attached to serial channel 2.
A  remote networking example is given in Listing 5; please, refer to Figure  3 
for a diagramatic representation. When configuring a network, it helps to draw
diagramatic  representations like the ones of Figures 1, 2, and 3, to  aid  in
visualizing the network.

Listing 5
MASTER.GEN  ;TurboDOS operating system Master GENeration file
NETREQ          ;Network request module
MSGFMT          ;Message format tables for NETREQ
LSTCTS          ;Printer driver for CTS hardware handshake
LSTPAR          ;Printer driver for Parallel handshake

MASTER.PAR  ;TurboDOS operating system PARameter file
CONAST = 00,CONDRA              ;First  serial channel -- Console terminal
PTRAST = 01,LSTDRA              ;Second serial channel -- First printer driver
         00,LSTDRB              ;Parallel channel -- Second printer driver
         80,(0001)              ;Printer C is printer A on R-node#1
         80,(0002)              ;Printer D is printer A on R-node #2
QUEAST = 0,(0),0,(0)            ;Queues A and B are valid Local queues
         80,(0001),80,(0002)    ;Queues C and D are valid Remote queues
DSPPAT = 01,02,03,04            ;Printer A to Queue A, B to B, etc.
CTSBR = 6E                      ;CTS printer at 9600 baud

SLAVE1.GEN  ;TurboDOS operating system Slave 1 GENeration file
NETSVC          ;Network service local printer request
DSPOOL          ;Print despooler for local printer
LSTETX          ;Printer driver for ETX/ACK handshake

SLAVE1.PAR  ;TurboDOS operating system Slave 1 PARameter file
PTRAST = 01,LSTDRA                 ;2nd serial channel -- 1st printer driver
         0FF,(0),0FF,(0),0FF,(0)        ;Printers B, C, D are Invalid
QUEAST = 0,(0)                          ;Local Queue A is Valid
         0FF,(0),0FF,(0),0FF,(0)        ;Queues B, C, and D are Invalid
ETXBR = 0C                              ;ETX/ACK handshaking at 4800 baud

SLAVE2.GEN  ;TurboDOS operating system Slave 2 GENeration file
NETSVC          ;Network service local printer request
DSPOOL          ;Print despooler for local printer
LSTXON          ;Printer driver for XON handshake

SLAVE2.PAR  ;TurboDOS operating system Slave 2 PARameter file
PTRAST = 01,LSTDRA              ;Second serial channel -- First printer driver
         82,(0000)              ;Printer B is printer C on R-node #0
         0FF,(0),0FF,(0)        ;Printers C and D are Invalid
QUEAST = O,(0)                  ;Local Queue A is valid
         82,(0)                 ;Queue B is Queue C on R-node #0
         0FF,(0),0FF,(0)        ;Queues C and D are Invalid
DSPPAT = 01,02                  ;Printer A to Queue A,B to B, etc.

SLAVE3.GEN  ;TurboDOS operating system Slave 3 GENeration file
LST300          ;Serial driver default 300 baud
                ;NETSVC required because of no local printer

SLAVE3.PAR  ;TurboDOS operating system Slave 3 PARameter file (Example 1)
PTRAST = 80,(0000)              ;Printer A is printer A on R-node #0
         81,(0000)              ;Printer B is printer B on R-node #0
         01,LSTDRA              ;Printer C is a Local printer
         0FF,(0000)             ;Printer D is Invalid
QUEAST = 80,(0)                 ;Queue A is Queue A on R-node #0
         81,(0)                 ;Queue B is Queue B on R-node #0
         0FF,(0),OFF,(0)        ;Queues C and D are Invalid
DSPPAT = 01,02                  ;Printer A to Queue A, B to B
                                ;No baud rate specified, so it goes to default

SLAVE3.PAR  ;TurboDOS operating system Slave 3 PARameter file (Example 2)
PTRAST +6 = 01,LSTDRA,0FF,(0)   ;Offset of 6 bytes for first 2 printers A and B
                                ;Printers A and B default to the server PTRAST
QUEAST +6 = 0FF,(0)             ;6-byte offset for the 2 system printers off
                                ;the server.
            0FF,(0)             ;Queues C and D are Invalid
DSPPAT = 01,02                  ;Queue A to Queue A, B to B

SLAVE4.PAR  ;TurboDOS operating system Slave 4 PARameter file
This satellite does not require any printer drivers in the SLAVE4.GEN file. In 
the  SLAVE4.PAR  file, it will require no printer or  queue  assignment.  This
satellite  defaults  to the server, but a sample PAR file is  shown  below  to
illustrate the defaults.
PTRAST = 80,(0),81,(0)          ;Defaults for system printers
QUEAST = 80,0),81,(0)           ;Defaults Queues for system printers
        Figure 3. Remote printer networking