Listing 1 (PAR_COMM.C)

/* Description: Library of functions to support
bidirection communications with PC parallel port.

Global Function List: correct_bios_status
                  correct_port_status
                  get_prn_port
                  in_bios_nibble
                  in_bios_status
                  in_port_nibble
                  in_port_status
                  invert_bit

Portability: MS-DOS Microsoft C or Borland C */

/* Standard C */
#include <bios.h>
#include <conio.h>

/* Own */
#include <par_comm.h>
#if !defined ( FAR )
   #define FAR _far
#endif

/*     Name: correct_bios_status
 Parameters: Status - printer port status
    Return: Corrected printer port status

Description: Corrects the printer status that was obtained
using the BIOS so it matches the actual line levels.*/

unsigned correct_bios_status( unsigned Status )
   {
   Status = invert_bit( Status, 7 );
   Status = invert_bit( Status, 6 );
   return ( Status );
   }

/*     Name: correct_bios_status
 Parameters: Status - printer port status
    Return: Corrected printer port status

Description: Corrects the printer status that was obtained
directly from the port so it matches the actual line
levels.*/

unsigned correct_port_status( unsigned Status )
   {
   Status = invert_bit( Status, 7 );
   Status = invert_bit( Status, 3 );
   return ( Status );
   }

/*     Name: get_prn_port
 Parameters: PrnNum - number of the printer device
           LPT1 - 0, LPT2 - 1, LPT3 - 2, LPT4 - 3
    Return: printer port number

Description: Retrives the printer port number from the
PC's printer data table.*/

unsigned get_prn_port( unsigned PrnNum )
   {
   return ( *((unsigned FAR *)(( 0x40LU << 16 ) |
        ( 0x08U + 2 * PrnNum ))));
   }

/*     Name: in_bios_nibble
 Parameters: PrnPort - address of printer port
    Return: Nibble read in from printer port

Description: Inputs a nibble from a printer port using a
call to the PC's BIOS. The status lines are read and
corrected. The high nibble of the status lines is stored in
the low nibble of the return value. Bit 3 of the status is
used to set the sign bit of the return value.*/

unsigned in_bios_nibble( unsigned PrnNum )
   {
   unsigned Nibble;
   Nibble = _bios_printer( _PRINTER_STATUS,
        PrnNum, 0 );
   Nibble = correct_bios_status( Nibble );
   Nibble = ( Nibble << ( sizeof( unsigned ) * 8 - 4
        )) | ( Nibble >> 4 );
   return ( Nibble );
   }

/*     Name: in_bios_status
 Parameters: PrnNum - number of the printer device
           LPT1 - 0, LPT2 - 1, LPT3 - 2, LPT4 - 3
    Return: printer status bits in low byte

Description: Gets the status byte from a printer port
using the BIOS.*/

unsigned in_bios_status( unsigned PrnNum )
   {
   return ( _bios_printer( _PRINTER_STATUS,
        PrnNum, 0 ));
   }

/*     Name: in_port_nibble
 Parameters: PrnPort - address of printer port
    Return: Nibble read in from printer port

Description: Inputs a nibble from a printer port with a
direct read from the port. The status lines are read and
corrected. The high nibble of the status lines is
stored in the low nibble of the return value. Bit 3 of
the status is used to set the sign bit of the return
value.*/

unsigned in_port_nibble( unsigned PrnPort )
   {
   unsigned Nibble;
   
   Nibble = in_port_status( PrnPort );
   Nibble = correct_port_status( Nibble );
   Nibble = ( Nibble << ( sizeof( unsigned ) * 8 - 4
        )) | ( Nibble >> 4 );
   return ( Nibble );
   }

/*     Name: in_port_status
 Parameters: PrnPort - printer port number
    Return: printer status bits in low byte

Description: Gets the status byte from a printer port and
masks off the lower three bits.*/

unsigned in_port_status( unsigned PrnPort )
   {
   return ( 504 /* 11111000 */ & inp( PrnPort + 1 ));
   }

/*     Name: invert_bit
 Parameters: Val - value to invert a single bit in
           Bit - number of bit in Val to invert
    Return: Val with Bit inverted
Description: Inverts a single designated bit in Val.*/

unsigned invert_bit( unsigned Val, unsigned Bit )
   {
   return (( Val & ~( 1U << Bit )) |
        (( !(( Val >> Bit ) & 1U )) << Bit ));
   }
/* End of File */