[comp.lang.pascal] Help - com1 port output via TP5.5

wjt@psc90.UUCP (Bill Taffe) (07/12/90)

I remember something similar to this being discussed a few months
ago, so if this is a repeated request please forgive.

I'm trying to send characters to a HP plotter (HP GL commands)
through the com1 port using TP5.5.  It was easy in TP3 where you only
had to reference com1 in the write statements.  TP5.5 is more
difficult.

I've tried the AuxInOut unit in the manual (p212) and can't get it to
work for me.  The test program (p215) 'hangs up' at the Rewrite(Com1)
statement.  (I've replaced the "Device Drivers ... "line with HPGL
commands).

I'm using a Z-248 (AT compatible).

Has anyone had experience sending characters through Com1 using
TP5.5?  Anyone run into this problem?

Suggestions and/or working code/units gratefully accepted.  Thanks.

Bill Taffe
Plymouth State College  (NH)
wjt@psc90.uucp  
(soon to be wjt@oz.plymouth.edu)

nboogaar@ruunsa.fys.ruu.nl (Martin v.d. Boogaard) (07/13/90)

In <1444@psc90.UUCP> wjt@psc90.UUCP (Bill Taffe) writes:

>I've tried the AuxInOut unit in the manual (p212) and can't get it to
>work for me.  

Neither could I.

>Suggestions and/or working code/units gratefully accepted.  Thanks.

The solution below is *not* elegant, but it does work. Baud rates up to
19200 are no problem and you can set COM port parameters that are not
accepted by e.g. MODE.


Martin J. van den Boogaard         | Dept. of Atomic & Interface Physics
                                   | Debye Institute--Utrecht University
P.O. Box 80.000                    |
NL-3508 TA  Utrecht                | decnet:   ruunsc::boogaard
the Netherlands                    | bitnet:   boogaard@hutruu51
+31 30 532904                      | internet: nboogaar@fys.ruu.nl

---------------------------------cut here-----------------------------------

unit Auxio;

{I/O through the IBM's serial ports; the result of each I/O request can be
 found in the byte Auxresult. The machine language loops in the routines that
 check the line status can not be stopped by ctrl-break or ctrl-c if the loop
 termination condition is never met. This is done to make the timing of the
 loops independent of the sometimes inpredictable duration of DOS interrupts
 or BIOS routines. The routines which read from the port (Auxr, Auxrl,
 Auxstatus) disable interrupts temporarily with the same purpose.

 Martin J. van den Boogaard,
 Dept. of Atomic and Interface Physics, R.U. Utrecht
 August 1989}

{#############################################################################}

interface

const Strl    = 127;

type Aux_line = string [ Strl ];

{-----------------------------------------------------------------------------}

procedure Auxset      ( Portnr:                 byte;
                        Rate:                   longint;
                        Parity:                 char;
                        Databits:               byte;
                        Stopbits:               byte );
function  Auxstatus   ( Portnr:                 byte ):   byte;
procedure Auxw        ( Portnr:                 byte;
                        Cha:                    char );
procedure Auxr        ( Portnr:                 byte;
                        var Cha:                char );
procedure Auxwl       ( Portnr:                 byte;
                        Str:                    Aux_line );
procedure Auxrl       ( Portnr:                 byte;
                        var Str:                Aux_line );
procedure Auxshow     ( Portnr:                 byte );

{-----------------------------------------------------------------------------}

var Auxresult:   byte;      {Indicates result of most recently called routine.}

{#############################################################################}

implementation

{-----------------------------------------------------------------------------}

procedure Auxset ( Portnr:                 byte;
                   Rate:                   longint;
                   Parity:                 char;
                   Databits:               byte;
                   Stopbits:               byte     );

{ Sets the specified port as desired. Accepts as baudrate any value between
  32 and 115200. The actual baudrate will be F / ( F DIV Rate ), where
  F = 115200, the maximum baudrate. Parity can be 'n', 'o' or 'e',
  data bits 5, 6, 7 or 8, stop bits 1 or 2. Selection of 2 stop bits actually
  implies 2 stop bits (if 6 or more data bits are selected) or 3/2 stop bit
  (if 5 data bits are selected).

  Auxresult has the one of the following values after execution of Auxset:
    0: success;
    1: specified port does not exist;
    2: illegal baudrate;
    3: illegal parity character;
    4: illegal number of data bits;
    5: illegal number of stop bits.}

begin {Auxset}
  inline (
    $BA/$00/$00/       { MOV   DX,0000        }
    $8E/$C2/           { MOV   ES,DX          }      {ES (0000) points at bios}
    $8A/$86/>Portnr/   { MOV   AL,[BP+@Portnr]}             {load portnr in AL}
    $D0/$E0/           { SHL   AL,1           }
    $B4/$00/           { MOV   AH,00          }         {port addresses are at}
    $BB/$00/$04/       { MOV   BX,0400        }        {0000:0400, 0000:0402..}
    $01/$C3/           { ADD   BX,AX          } {find location of port address}
    $26/               { ES:                  }               {force use of ES}
    $8B/$17/           { MOV   DX,[BX]        }             {load port address}
    $F7/$C2/$FF/$FF/   { TEST  DX,FFFF        }           {anything sensible ?}
    $75/$03/           { JNZ   port_done      }
    $E9/$9D/$00/       { JMP   error_exit_1   }      {error if port is unknown}
                       {port_done:            }
    $8B/$8E/>Rate/     { MOV   CX,[BP+@Rate]  }           {load baudrate in CX}
    $8B/$96/>Rate+2/   { MOV   DX,[BP+@Rate+2]}                        {and DX}
    $83/$FA/$00/       { CMP   DX,00          }       {test baudrate high word}
    $74/$16/           { JE    low_baudrate   }              {baudrate < 65536}
    $83/$FA/$01/       { CMP   DX,01          } {test baudrate high word again}
    $74/$03/           { JE    test_low_word  }
    $E9/$90/$00/       { JMP   error_exit_2   }             {baudrate too high}
                       {test_low_word:        }
    $81/$F9/$00/$C2/   { CMP   CX,C200        }        {test baudrate low word}
    $76/$03/           { JBE   high_baudrate  }
    $E9/$87/$00/       { JMP   error_exit_2   }             {baudrate too high}
                       {high_baudrate:        }
    $B9/$01/$00/       { MOV   CX,0001        }             {baudrate = 115200}
    $EB/$0F/           { JMP   set_baudrate   }
                       {low_baudrate:         }
    $83/$F9/$20/       { CMP   CX,0020        }  {test baudrate low word again}
    $72/$7D/           { JB    error_exit_2   }            {baudrate too small}
    $B8/$00/$C2/       { MOV   AX,C200        }
    $BA/$01/$00/       { MOV   DX,0001        } {load max frequency, 115.2 KhZ}
    $F7/$F1/           { DIV   CX             }        {calculate divisor word}
    $89/$C1/           { MOV   CX,AX          }       {load divisor word in CX}
                       {set_baudrate:         }
    $26/               { ES:                  }               {force use of ES}
    $8B/$17/           { MOV   DX,[BX]        }             {load port address}
    $83/$C2/$03/       { ADD   DX,03          }  {select line control register}
    $EC/               { IN    AL,DX          }        {load line control byte}
    $0C/$80/           { OR    AL,80          }       {select divisor register}
    $EE/               { OUT   DX,AL          }       {store line control byte}
    $83/$EA/$03/       { SUB   DX,03          }       {select divisor register}
    $89/$C8/           { MOV   AX,CX          }      {get divisor word from CX}
    $EF/               { OUT   DX,AX          }  {store it in divisor register}
    $83/$C2/$03/       { ADD   DX,03          }  {select line control register}
    $EC/               { IN    AL,DX          }        {load line control byte}
    $24/$7F/           { AND   AL,7F          }              {select rx buffer}
    $EE/               { OUT   DX,AL          }       {store line control byte}
    $8A/$86/>Parity/   { MOV   AL,[BP+@Parity]}        {load parity char in AL}
    $3C/$61/           { CMP   AL,61          }           {is char lowercase ?}
    $72/$02/           { JB    uppercase      }
    $2C/$20/           { SUB   AL,20          }     {then convert to uppercase}
                       {uppercase:            }
    $3C/$4E/           { CMP   AL,4E          }                        { 'N' ?}
    $75/$06/           { JNE   enable_parity  }
    $EC/               { IN    AL,DX          }        {load line control byte}
    $24/$F7/           { AND   AL,F7          }       {clear parity enable bit}
    $EE/               { OUT   DX,AL          }       {store line control byte}
    $EB/$14/           { JMP   parity_done    }
                       {enable_parity:        }
    $3C/$45/           { CMP   AL,45          }                        { 'E' ?}
    $75/$06/           { JNE   no_even_parity }
    $EC/               { IN    AL,DX          }        {load line control byte}
    $0C/$18/           { OR    AL,18          }            {enable even parity}
    $EE/               { OUT   DX,AL          }       {store line control byte}
    $EB/$0A/           { JMP   parity_done    }
                       {no_even_parity:       }
    $3C/$4F/           { CMP   AL,4F          }                        { 'O' ?}
    $75/$42/           { JNE   error_exit_3   }      {illegal parity character}
    $EC/               { IN    AL,DX          }        {load line control byte}
    $0C/$08/           { OR    AL,08          }         {set parity enable bit}
    $24/$EF/           { AND   AL,EF          }             {select odd parity}
    $EE/               { OUT   DX,AL          }       {store line control byte}
                       {parity_done:          }
    $8A/$86/>Databits/ { MOV   AL,[BP+@Databits]}         {load databits in AL}
    $2C/$05/           { SUB   AL,05          }            {move to range 0..3}
    $78/$3C/           { JS    error_exit_4   }                {negative value}
    $3C/$03/           { CMP   AL,03          }    {should be within the range}
    $77/$38/           { JA    error_exit_4   }                     {value > 3}
    $88/$C1/           { MOV   CL,AL          }         {put value aside in CL}
    $EC/               { IN    AL,DX          }        {load line control byte}
    $24/$FC/           { AND   AL,FC          }           {reset databits bits}
    $08/$C8/           { OR    AL,CL          }     {set them to desired value}
    $EE/               { OUT   DX,AL          }       {store line control byte}
    $8A/$86/>Stopbits/ { MOV   AL,[BP+@Stopbits]}         {load stopbits in AL}
    $3C/$01/           { CMP   AL,01          }                  {1 stop bit ?}
    $75/$06/           { JNE   not_one_stopbit}
    $EC/               { IN    AL,DX          }        {load line control byte}
    $24/$FB/           { AND   AL,FB          }            {select 0 stop bits}
    $EE/               { OUT   DX,AL          }       {store line control byte}
    $EB/$32/           { JMP   normal_exit:   }
                       {not_one_stopbit:      }
    $3C/$02/           { CMP   AL,02          }            {2 or 3/2 stop bits}
    $75/$26/           { JNE   error_exit_5   }   {illegal number of stop bits}
    $EC/               { IN    AL,DX          }        {load line control byte}
    $0C/$04/           { OR    AL,04          }     {select 2 or 3/2 stop bits}
    $EE/               { OUT   DX,AL          }       {store line control byte}
    $EB/$28/           { JMP   normal_exit    }
                       {error_exit_1:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$01/       { MOV   BYTE PTR [BX],01}        {error 1: no such port}
    $EB/$26/           { JMP   finished       }
                       {error_exit_2:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$02/       { MOV   BYTE PTR [BX],02}    {error 2: illegal baudrate}
    $EB/$1E/           { JMP   finished       }
                       {error_exit_3:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$03/       { MOV   BYTE PTR [BX],03}     {error 3: ill parity char}
    $EB/$16/           { JMP   finished       }
                       {error_exit_4:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$04/       { MOV   BYTE PTR [BX],04}   {error 4: ill num data bits}
    $EB/$0E/           { JMP   finished       }
                       {error_exit_5:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$05/       { MOV   BYTE PTR [BX],05}   {error 5: ill num stop bits}
    $EB/$06/           { JMP   finished       }
                       {normal_exit:          }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$00        { MOV   BYTE PTR [BX],00}           {OK: Auxresult := 0}
                       {finished:             }
  );
end; {Auxset}

{-----------------------------------------------------------------------------}

function Auxstatus ( Portnr: byte ): byte;

{ Auxstatus returns the line status of the specified port.

  bit #     indication
  --------------------
    0       data ready
    1       overrun error
    2       parity error
    3       framing error
    4       break detected
    5       tx reg empty
    6       tx sh reg empty
    7       time out

  Auxresult has the one of the following values after execution of Auxstatus:
    0: success;
    1: specified port does not exist; Auxstatus is undefined.}

begin {Auxstatus}
  inline (
    $FA/               { CLI                  }                {do not disturb}
    $BA/$00/$00/       { MOV   DX,0000        }
    $8E/$C2/           { MOV   ES,DX          }      {ES (0000) points at bios}
    $8A/$86/>Portnr/   { MOV   AL,[BP+@Portnr]}             {load portnr in AL}
    $D0/$E0/           { SHL   AL,1           }
    $B4/$00/           { MOV   AH,00          }         {port addresses are at}
    $BB/$00/$04/       { MOV   BX,0400        }        {0000:0400, 0000:0402..}
    $01/$C3/           { ADD   BX,AX          } {find location of port address}
    $26/               { ES:                  }               {force use of ES}
    $8B/$17/           { MOV   DX,[BX]        }             {load port address}
    $F7/$C2/$FF/$FF/   { TEST  DX,FFFF        }           {anything sensible ?}
    $74/$0A/           { JZ    error_exit_1   }      {error if port is unknown}
    $83/$C2/$05/       { ADD   DX,05          }{switch to line status register}
    $EC/               { IN    AL,DX          }               {get port status}
    $88/$86/>Auxstatus/{ MOV   [BP+Auxstatus],AL}  {keep AL as function result}
    $EB/$08/           { JMP   normal_exit    }
                       {error_exit_1:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$01/       { MOV   BYTE PTR [BX],01}        {error 1: no such port}
    $EB/$06/           { JMP   finished       }
                       {normal_exit:          }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$00/       { MOV   BYTE PTR [BX],00}           {OK: Auxresult := 0}
                       {finished:             }
    $FB                { STI                  }               {be social again}
  );
end; {Auxstatus}

{-----------------------------------------------------------------------------}

procedure Auxw ( Portnr: byte;
                 Cha:    char );

{ Writes one character to the specified port as soon as the `transmit shift
  register empty' bit in the line control register is set. Auxw does
  (deliberately) not time out.

  Auxresult has the one of the following values after execution of Auxw:
    0: success;
    1: specified port does not exist.}

begin {Auxw}
  inline (
    $BA/$00/$00/       { MOV   DX,0000        }
    $8E/$C2/           { MOV   ES,DX          }      {ES (0000) points at bios}
    $8A/$86/>Portnr/   { MOV   AL,[BP+@Portnr]}             {load portnr in AL}
    $D0/$E0/           { SHL   AL,1           }
    $B4/$00/           { MOV   AH,00          }         {port addresses are at}
    $BB/$00/$04/       { MOV   BX,0400        }        {0000:0400, 0000:0402..}
    $01/$C3/           { ADD   BX,AX          } {find location of port address}
    $26/               { ES:                  }               {force use of ES}
    $8B/$17/           { MOV   DX,[BX]        }             {load port address}
    $F7/$C2/$FF/$FF/   { TEST  DX,FFFF        }           {anything sensible ?}
    $74/$13/           { JZ    error_exit_1   }      {error if port is unknown}
    $83/$C2/$05/       { ADD   DX,05          }{switch to line status register}
                       {check_again:          }
    $EC/               { IN    AL,DX          }               {get port status}
    $25/$40/$00/       { AND   AX,0040        } {keep `tx shift reg empty' bit}
    $74/$FA/           { JZ    check_again    }           {try again if not ok}
    $83/$EA/$05/       { SUB   DX,05          }  {switch to line transm buffer}
    $8A/$86/>Cha/      { MOV   AL,[BP+@Cha]   }                {load Cha in AL}
    $EE/               { OUT   DX,AL          }                    {write byte}
    $EB/$08/           { JMP   normal_exit    }
                       {error_exit_1:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$01/       { MOV   BYTE PTR [BX],01}        {error 1: no such port}
    $EB/$06/           { JMP   finished       }
                       {normal_exit:          }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$00        { MOV   BYTE PTR [BX],00}           {OK: Auxresult := 0}
                       {finished:             }
  );
end; {Auxw}

{-----------------------------------------------------------------------------}

procedure Auxr ( Portnr:  byte;
                 var Cha: char );

{ Reads one character from the specified port as soon as the `data ready' bit
  in the line control register is set. Auxr does (deliberately) not time out.

  Auxresult has the one of the following values after execution of Auxw:
    0: success;
    1: specified port does not exist.}

begin {Auxr}
  inline (
    $FA/               { CLI                  }                {do not disturb}
    $BA/$00/$00/       { MOV   DX,0000        }
    $8E/$C2/           { MOV   ES,DX          }      {ES (0000) points at bios}
    $8A/$86/>Portnr/   { MOV   AL,[BP+@Portnr]}             {load portnr in AL}
    $D0/$E0/           { SHL   AL,1           }
    $B4/$00/           { MOV   AH,00          }         {port addresses are at}
    $BB/$00/$04/       { MOV   BX,0400        }        {0000:0400, 0000:0402..}
    $01/$C3/           { ADD   BX,AX          } {find location of port address}
    $26/               { ES:                  }               {force use of ES}
    $8B/$17/           { MOV   DX,[BX]        }             {load port address}
    $F7/$C2/$FF/$FF/   { TEST  DX,FFFF        }           {anything sensible ?}
    $74/$17/           { JZ    error_exit_1   }      {error if port is unknown}
    $1E/               { PUSH  DS             }                       {save DS}
    $83/$C2/$05/       { ADD   DX,05          }{switch to line status register}
                       {check_again:          }
    $EC/               { IN    AL,DX          }               {get port status}
    $25/$01/$00/       { AND   AX,0001        }         {keep `data ready' bit}
    $74/$FA/           { JZ    check_again    }           {try again if not ok}
    $83/$EA/$05/       { SUB   DX,05          }{switch to line receiver buffer}
    $EC/               { IN    AL,DX          }                     {read byte}
    $C5/$9E/>Cha/      { LDS   BX,[BP+@Cha]   }
    $88/$07/           { MOV   [BX],AL        }             {store byte in Cha}
    $1F/               { POP   DS             }                    {restore DS}
    $EB/$08/           { JMP   normal_exit    }
                       {error_exit_1:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$01/       { MOV   BYTE PTR [BX],01}        {error 1: no such port}
    $EB/$06/           { JMP   finished       }
                       {normal_exit:          }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$00/       { MOV   BYTE PTR [BX],00}           {OK: Auxresult := 0}
                       {finished:             }
    $FB                { STI                  }               {be social again}
  );
end; {Auxr}

{-----------------------------------------------------------------------------}

procedure Auxwl ( Portnr:   byte;
                  Str:      Aux_line );

{ Writes a string to the specified port as soon as the `transmit shift
  register empty' bit in the line control register is set. Auxw does
  (deliberately) not time out. Immediately after writing a character (except
  after the final <CR> that is added by Auxwl) writing is interrupted for
  a short period of time (between 55 and 110 ms) to enable the receiving
  device to process the character just written.

  Auxresult has the one of the following values after execution of Auxwl:
    0: success;
    1: specified port does not exist.}

begin {Auxwl}
  inline (
    $BA/$00/$00/       { MOV   DX,0000        }
    $8E/$C2/           { MOV   ES,DX          }      {ES (0000) points at bios}
    $8A/$86/>Portnr/   { MOV   AL,[BP+@Portnr]}             {load portnr in AL}
    $D0/$E0/           { SHL   AL,1           }
    $B4/$00/           { MOV   AH,00          }         {port addresses are at}
    $BB/$00/$04/       { MOV   BX,0400        }        {0000:0400, 0000:0402..}
    $01/$C3/           { ADD   BX,AX          } {find location of port address}
    $26/               { ES:                  }               {force use of ES}
    $8B/$17/           { MOV   DX,[BX]        }             {load port address}
    $F7/$C2/$FF/$FF/   { TEST  DX,FFFF        }           {anything sensible ?}
    $74/$47/           { JZ    error_exit_1   }      {error if port is unknown}
    $1E/               { PUSH  DS             }                       {save DS}
    $8A/$8E/>Str/      { MOV   CL,[BP+@Str]   }          {load num chars in CX}
    $80/$F9/$00/       { CMP   CL,00          }            {if string is empty}
    $74/$2B/           { JE    write_cr       }               {only write <CR>}
    $B5/$00/           { MOV   CH,00          }
    $16/               { PUSH  SS             }           {make DS equal to SS}
    $1F/               { POP   DS             }
    $89/$EE/           { MOV   SI,BP          }
    $81/$C6/>Str/      { ADD   SI,@Str        }
    $46/               { INC   SI             } {SI points at first char in SI}
    $FC/               { CLD                  }         {select to increase SI}
                       {write_again:          }
    $83/$C2/$05/       { ADD   DX,05          }{switch to line status register}
                       {check_again_1:        }
    $EC/               { IN    AL,DX          }               {get port status}
    $25/$40/$00/       { AND   AX,0040        } {keep `tx shift reg empty' bit}
    $74/$FA/           { JZ    check_again_1  }           {try again if not ok}
    $83/$EA/$05/       { SUB   DX,05          }  {switch to line transm buffer}
    $AC/               { LODSB                }       {load char to be written}
    $EE/               { OUT   DX,AL          }                    {write byte}
    $BB/$6C/$04/       { MOV   BX,046C        }          {0000:046C, clock LSB}
    $26/               { ES:                  }               {force use of ES}
    $8A/$07/           { MOV   AL,[BX]        }      {load initial clock value}
    $04/$02/           { ADD   AL,02          }   {wait 1 or 2 cycles of 55 ms}
                       {wait:                 }
    $26/               { ES:                  }
    $8A/$27/           { MOV   AH,[BX]        }      {load current clock value}
    $38/$C4/           { CMP   AH,AL          }
    $75/$F9/           { JNE   wait           }
    $E2/$E1/           { LOOP  write_again    } {if more chars, write next one}
                       {write_cr:             }
    $83/$C2/$05/       { ADD   DX,05          }{switch to line status register}
                       {check_again_2:          }
    $EC/               { IN    AL,DX          }               {get port status}
    $25/$40/$00/       { AND   AX,0040        } {keep `tx shift reg empty' bit}
    $74/$FA/           { JZ    check_again_2  }           {try again if not ok}
    $83/$EA/$05/       { SUB   DX,05          }  {switch to line transm buffer}
    $B0/$0D/           { MOV   AL,0D          }               {load <CR> in AL}
    $EE/               { OUT   DX,AL          }                    {write <CR>}
    $1F/               { POP   DS             }                    {restore DS}
    $EB/$08/           { JMP   normal_exit    }
                       {error_exit_1:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$01/       { MOV   BYTE PTR [BX],01}        {error 1: no such port}
    $EB/$06/           { JMP   finished       }
                       {normal_exit:          }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$00        { MOV   BYTE PTR [BX],00}           {OK: Auxresult := 0}
                       {finished:             }
  );
end; {Auxwl}

{-----------------------------------------------------------------------------}

procedure Auxrl ( Portnr:       byte;
                  var Str:      Aux_line );

{ Reads a string (i.e. a sequence of characters terminated by a <CR>) from the
  specified port. Each character is read only after the `data ready' bit in
  the line control register has been set. Auxr does (deliberately) not time
  out.

  Auxresult has the one of the following values after execution of Auxrl:
    0: success;
    1: specified port does not exist.}

begin {Auxrl}
  inline (
    $FA/               { CLI                  }                {do not disturb}
    $1E/               { PUSH  DS             }                       {save DS}
    $BA/$00/$00/       { MOV   DX,0000        }
    $8E/$C2/           { MOV   ES,DX          }      {ES (0000) points at bios}
    $8A/$86/>Portnr/   { MOV   AL,[BP+@Portnr]}             {load portnr in AL}
    $D0/$E0/           { SHL   AL,1           }
    $B4/$00/           { MOV   AH,00          }         {port addresses are at}
    $BB/$00/$04/       { MOV   BX,0400        }        {0000:0400, 0000:0402..}
    $01/$C3/           { ADD   BX,AX          } {find location of port address}
    $26/               { ES:                  }               {force use of ES}
    $8B/$17/           { MOV   DX,[BX]        }             {load port address}
    $F7/$C2/$FF/$FF/   { TEST  DX,FFFF        }           {anything sensible ?}
    $74/$28/           { JZ    error_exit_1   }      {error if port is unknown}
    $C4/$BE/>Str/      { LES   DI,[BP+@Str]   }
    $47/               { INC   DI             }   {address of first char in DI}
    $FC/               { CLD                  }         {select to increase DI}
    $B9/>Strl/         { MOV   CX,Strl        }       {initialize char counter}
                       {read_again            }
    $83/$C2/$05/       { ADD   DX,05          }{switch to line status register}
                       {check_again:          }
    $EC/               { IN    AL,DX          }               {get port status}
    $25/$01/$00/       { AND   AX,0001        }         {keep `data ready' bit}
    $74/$FA/           { JZ    check_again    }           {try again if not ok}
    $83/$EA/$05/       { SUB   DX,05          }{switch to line receiver buffer}
    $EC/               { IN    AL,DX          }                     {read byte}
    $3C/$0D/           { CMP   AL,0D          }                {is byte <CR> ?}
    $74/$03/           { JE    ready          }
    $AA/               { STOSB                }
    $E2/$EC/           { LOOP  read_again     } {if space left, read next char}
                       {ready:                }
    $C5/$9E/>Str/      { LDS   BX,[BP+@Str]   }
    $C6/$07/<Strl/     { MOV   BYTE PTR [BX],Strl}
    $28/$0F/           { SUB   [BX],CL        }        {store length in Str[0]}
    $EB/$08/           { JMP   normal_exit    }
                       {error_exit_1:         }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$01/       { MOV   BYTE PTR [BX],01}        {error 1: no such port}
    $EB/$06/           { JMP   finished       }
                       {normal_exit:          }
    $BB/>Auxresult/    { MOV   BX,@Auxresult  }
    $C6/$07/$00/       { MOV   BYTE PTR [BX],00}           {OK: Auxresult := 0}
                       {finished:             }
    $1F/               { POP   DS             }                    {restore DS}
    $FB                { STI                  }               {be social again}
  );
end; {Auxrl}

{-----------------------------------------------------------------------------}

procedure Auxshow ( Portnr: byte );

{ Displays the current status of the specified port on the screen. Auxshow is
  a routine intended typically for debugging communication routines that hangup
  because of a fault in the port status immediately prior to a call to Auxr or
  Auxw.}

var Auxstat: byte;

begin {Auxshow}
  Auxstat := Auxstatus ( Portnr );
  if Auxstat > 0
  then
    begin
      writeln ( 'The following bits are set for port ', Portnr:0, ':' );
      if ( Auxstat and $01 > 0 ) then writeln ( ' - data ready' );
      if ( Auxstat and $02 > 0 ) then writeln ( ' - overrun error' );
      if ( Auxstat and $04 > 0 ) then writeln ( ' - parity error' );
      if ( Auxstat and $08 > 0 ) then writeln ( ' - framing error' );
      if ( Auxstat and $10 > 0 ) then writeln ( ' - break detected' );
      if ( Auxstat and $20 > 0 ) then writeln ( ' - tx reg empty' );
      if ( Auxstat and $40 > 0 ) then writeln ( ' - tx sh reg empty' );
      if ( Auxstat and $80 > 0 ) then writeln ( ' - time out' );
    end
  else
    writeln ( 'All bits are clear for port ', Portnr:0, '.' );
end; {Auxshow}

{-----------------------------------------------------------------------------}

end.

{#############################################################################}