In no event shall the author be liable for any damages whatsoever for any loss relating to this document. Use it at your own risk!
The normal function of the port is to transfer data to a parallel printer through the eight data pins, using the remaining signals as flow control and miscellaneous controls and indications. A standard port does this using the Centronics parallel interface standard.
The original port was implemented with TTL/LS logic. Modern ports are
implemented in an ASIC (application-
The parallel port I/O address table contains up to three 16-bit words (four on
some BIOSes). Each entry gives the I/O base address of a parallel port. The
first word is the I/O base address of LPT1, the second is LPT2, etc. If less
than three ports were found, the remaining entries in the table are zero.
DOS, and the BIOS printer functions (accessed via int 17h), use this table to
translate an LPT port number to a port address, to access the appropriate
physical port.
The power-on self-test checks these addresses in a specific order, and
addresses are put into the table as they are found, so the table will never
have gaps. A particular I/O address does not necessarily always equate to the
same specific LPT port number, although there are conventions.
Data register: LPTBase+0, read/write, driven by software (driven by hardware in input mode)
Note: Signal names which start with '-' are electrically
active-low. For example the '-ERROR' signal indicates that an
error is present when it is low, and that no error is present when it is high.
Signal names without a leading '-' are electrically active-high.
Control register: LPTBase+2, read/write (see below), driven by software and hardware (see below)
Note: As described for the status register,
signal names which start with '-' are electrically active-low.
These four outputs are open collector outputs with pullup resistors, so if they
are set electrically high, an external device can force them low (only)
without stressing the driver in the PC, and they can be used as inputs.
To use them as inputs, write 0100 binary to the bottom four bits of the
control register. This sets the outputs all high, so they are pulled high by the
pullup resistors in the parallel port circuitry (which are typically 4700 ohms).
An external device can then pull them low, and you can read the pin states by
reading the control register. Remember to allow for the inversion on three of
the pins.
If you are using this technique, the control register is not strictly
'read/write', because you may not read what you write (or wrote).
The interrupt control bit controls a tri-state buffer that drives the IRQ
(interrupt request) line. Setting the bit to 1 enables the buffer, and
an IRQ will be triggered on each rising edge (low to high transition)
of the -ACK signal on pin 10 of the 25-pin connector. Disabling the
buffer allows other devices to use the IRQ line. Important note: some
older parallel ports trigger the interrupt on the falling edge of -ACK.
For experimenters, the interrupt facility is useful as a general-
The actual IRQ number is either hard-wired (by convention, the port at
3BCh uses IRQ7) or jumper-selectable (IRQ5 is a common alternative).
Sound cards, in particular, tend to use IRQ7 for their own purposes.
To use the IRQ you must also enable the interrupt via the interrupt mask
register in the interrupt controller, at I/O address 21h, and your
interrupt handler must send an EOI on exit. DOS technical programming
references have notes on writing interrupt handlers.
Electrical signal characteristics for the three 'direction/type' types are:
Another method (which will also work with all port types) links eight data bits
across to five status inputs and three control lines, which are
used as inputs. Other methods yielding a higher data
rate can be used if both ports are bidirectional. The
EPP and ECP have special hardware support for higher speeds
(around 1MB/s) and the ECP also supports
high-speed data transfer using DMA (direct memory addressing, a process where
the hardware is able to read and write data directly to or from memory without
the CPU's intervention).
These sample functions send and receive a byte of data. One program must be the
sender, the other must be the receiver. receive_byte() will be used
only on the receiver. transmit_byte() will be used only on the sender,
and will not return until the byte has been received and acknowledged by the
receiver. input_value() is used on both sender and receiver. In a
practical program like INTERLNK, protocols are required to control the
data direction and provide error checking, etc.
static unsigned int lpt_base; /* Set to base I/O address */
/* Return input value as five-bit number. If input has changed since
this function was last called, verify that the input is stable. */
unsigned int input_value(void) {
static unsigned char last_value = 0xFF;
auto unsigned char new1, new2;
new1 = inportb(lpt_base + 1) & 0xF8;
if (new1 != last_value) {
while (1) {
new2 = inportb(lpt_base + 1) & 0xF8;
if (new2 == new1) /* Wait for stable value */
break;
new1 = new2;
}
last_value = new1;
}
return (last_value ^ 0x80) >> 3;
}
/* Receive an 8-bit byte value, returns -1 if no data available yet */
signed int receive_byte(void) {
unsigned int portvalue, bytevalue;
portvalue = input_value(); /* Read input */
if ((portvalue & 0x10) == 0)
return -1; /* Await high flag */
outportb(lpt_base, 0x10); /* Assert reverse flag */
bytevalue = portvalue & 0x0F; /* Keep low nibble */
do {
portvalue = input_value();
} while ((portvalue & 0x10) != 0); /* Await low flag */
outportb(lpt_base, 0); /* Deassert reverse flag */
bytevalue |= (portvalue << 4); /* High nibble */
return bytevalue & 0xFF;
}
/* Transmit an 8-bit byte value, won't return until value is sent */
void transmit_byte(unsigned int val) {
val &= 0xFF;
outportb(lpt_base, (val & 0x0F) | 0x10); /* Set nibble flag */
while ((input_value() & 0x10) == 0)
; /* Await returned flag high */
outportb(lpt_base, val >> 4); /* Clear nibble flag */
while ((input_value() & 0x10) != 0)
; /* Await returned flag low */
return;
}
--------------------------- snip snip snip ---------------------------
Some parallel port cards may require a jumper change to allow input mode to be
selected. Machines with a parallel port integrated on the motherboard may
provide a BIOS setting to enable and disable bidirectional capability.
Bidirectional ports (PS/2 and compatible) use
control register bit 5 to enable input mode
(input mode is enabled while this bit is set to 1). Other ports with
input mode capability may enable input mode via a different signal, but I have
no details.
This program was written for Borland C. Change outportb() to
outp() and inportb() to inp() for Microsoft
C, I think. Save this code to BIDIR.C and compile with:
bcc -Iinclude_path -Llibrary_path bidir.c
#include <dos.h>
#include <process.h>
#include <stdio.h>
/* The following function returns the I/O base address of the nominated
parallel port. The input value must be 1 to 3. If the return value
is zero, the specified port does not exist. */
unsigned int get_lptport_iobase(unsigned int lptport_num) {
return *((unsigned int far *)MK_FP(0x40, 6) + lptport_num);
}
/* Checks whether the port's data register retains data, returns 1 if
so, 0 if not. The data register retains data on non-bidirectional
ports, but on bidirectional ports in high impedance (tri-state)
mode, the data register will not retain data. */
unsigned int test_retention(unsigned int iobase) {
outportb(iobase, 0x55); /* Write a new value */
(void) inportb(iobase); /* Delay */
if (inportb(iobase) != 0x55) {
return 0; /* Did not retain data */
}
outportb(iobase, 0xAA); /* Write another new value */
(void) inportb(iobase); /* Delay */
if (inportb(iobase) != 0xAA) {
return 0; /* Did not retain data */
}
return 1; /* Retained data alright */
}
void report_port_type(unsigned int portnum) {
unsigned int iobase, oldctrl, oldval;
iobase = get_lptport_iobase(portnum);
if (iobase == 0) {
printf("LPT%d does not exist\n", portnum);
return;
}
oldctrl = inportb(iobase+2);
outportb(iobase+2, oldctrl & 0xDF); /* Bidir off */
(void) inportb(iobase); /* Delay */
oldval = inportb(iobase); /* Keep old data */
if (test_retention(iobase) == 0) {
printf("LPT%d is faulty or set to input mode\n", portnum);
outportb(iobase+2, oldctrl);
outportb(iobase, oldval);
return;
}
outportb(iobase+2, oldctrl | 0x20); /* Bidir on for some ports */
if (test_retention(iobase))
printf("LPT%d is non-bidirectional or in standard mode\n", portnum);
else
printf("LPT%d is bidirectional using control port bit 5\n", portnum);
outportb(iobase+2, oldctrl); /* Put it back */
outportb(iobase, oldval); /* Restore data */
return;
}
void main(void) {
unsigned int portnum;
for (portnum = 1; portnum < 4; ++portnum)
report_port_type(portnum);
exit(0);
}
--------------------------- snip snip snip ---------------------------
The PS/2 bidirectional port is a standard port with
input mode capability, enabled via bit 5 of the
control register.
The EPP (Enhanced Parallel Port) and ECP (Extended Capabilities Port) are
described in the IEEE 1284 standard of 1994, which gives the
physical, I/O and BIOS interfaces. Both are backward-compatible with the
original parallel port, and add special modes which include bidirectional data
transfer capability. These modes support fast data transfer between computers
and printers, and between computers, and support multiple printers or other
peripherals on the same port. In their enhanced modes, they re-define the
control and status lines of the parallel port connector, using it as a slow
multiplexed parallel bus. The ECP supports DMA (direct memory access) for
automated high-speed data transfer.
http://www.pcgadgets.com/upcatlog.html
PC Gadgets (commercial) catalogue - parallel-port unit to drive stepper
motors and monitor switches.
http://www.senet.com.au/~cpeacock/
Craig Peacock's Interfacing the PC page - technical information on all port
types, links to relevant material, several PC interfacing projects.
The BIOS LPT Port Table
A parallel port is identified by its I/O base address, and
also by its LPT port number. The BIOS power-on self-test
checks specific I/O addresses for the presence of a parallel port, and builds
a table of I/O addresses in the low memory BIOS data area, starting at address
0040:0008 (or 0000:0408).Addressing Conventions
The video card's parallel port is normally at 3BCh. This address is
the first to be checked by the BIOS, so if a port exists there, it will become
LPT1. The BIOS then checks at 378h, then at 278h. I know of
no standard address for a fourth port.Direct Hardware Access
A parallel port consists of three 8-bit registers at adjacent addresses in the
processor's I/O space. The registers are defined relative to the I/O
base address, and are at IOBase+0, IOBase+1 and
IOBase+2 (for example if IOBase is 3BCh, then the
registers are at 3BCh, 3BDh and 3BEh).
Always use 8-bit I/O accesses on these registers.Data Register
The data register is at IOBase+0. It may be read and written
(using the IN and OUT instructions, or inportb() and
outportb() or inp() and outp()). Writing a byte to
this register causes the byte value to appear on the data signals, on pins 2 to
9 inclusive of the D-sub connector (unless the port is
bidirectional and is set to input mode). The value will
remain latched and stable until a different value is written to
the data register. Reading this register yields the state of the data signal
lines at the time of the read access. 7 6 5 4 3 2 1 0 Name Pin Buffer Bit value '0' meaning Bit value '1' meaning * . . . . . . . D7 9 True Pin low; data value '0' Pin high; data value '1' . * . . . . . . D6 8 True Pin low; data value '0' Pin high; data value '1' . . * . . . . . D5 7 True Pin low; data value '0' Pin high; data value '1' . . . * . . . . D4 6 True Pin low; data value '0' Pin high; data value '1' . . . . * . . . D3 5 True Pin low; data value '0' Pin high; data value '1' . . . . . * . . D2 4 True Pin low; data value '0' Pin high; data value '1' . . . . . . * . D1 3 True Pin low; data value '0' Pin high; data value '1' . . . . . . . * D0 2 True Pin low; data value '0' Pin high; data value '1' 7 6 5 4 3 2 1 0 Name Pin Buffer Bit value '0' meaning Bit value '1' meaning * . . . . . . . BUSY 11 Inverted Pin high; printer is busy Pin low; printer is not busy . * . . . . . . -ACK 10 True Pin low; printer is asserting -ACK Pin high; printer is not asserting -ACK . . * . . . . . NOPAPER 12 True Pin low; printer has paper Pin high; printer has no paper . . . * . . . . SELECTED 13 True Pin low; printer is not selected Pin high; printer is selected . . . . * . . . -ERROR 15 True Pin low; printer error condition Pin high; printer no-error condition . . . . . * * * Undefined Control Register
The control register is at IOBase+2. It can be read and written. Bits
7 and 6 are unimplemented (when read, they yield undefined values, often 1,1,
and when written, they are ignored). Bit 5 is also unimplemented on the standard
parallel port, but is a normal read/write bit on the PS/2
port. Bit 4 is a normal read/write bit. Bits 3, 2, 1 and 0 are special -
see the following section. 7 6 5 4 3 2 1 0 Name Pin Buffer Bit value '0' meaning Bit value '1' meaning * * . . . . . . Unused - - (undefined on read, ignored on write) . . * . . . . . Input mode - - Normal (output) mode Input mode (PS/2 ports only) . . . * . . . . Interrupt enable - - IRQ line driver disabled IRQ line driver enabled . . . . * . . . -SELECT 17 Inverted Pin high; not selected Pin low; printer selected . . . . . * . . -INITIALIZE 16 True Pin low; initializes printer Pin high; does not initialize printer . . . . . . * . -AUTOFEED 14 Inverted Pin high; no auto-feed Pin low; auto-feed enabled . . . . . . . * -STROBE 1 Inverted Pin high; -STROBE inactive Pin low; -STROBE active Printer Control Bits
The bottom four bits of the control register
are latched and presented on the parallel port connector, much like the data
register. Three of them are inverted, so writing a 1 will output a low
voltage on the port pin for them. When the parallel port is used for printing
in the normal way, using the Centronics standard, these four signals are used
as outputs (control signals to the printer).Interrupt Enable Bit
The parallel port interrupt was intended to allow interrupt-Pin Signal Direction/type
(see below) Register and bit Buffer Normal signal line function 1 -STROBE OC/Pullup Control register bit 0 Inverted Falling edge strobes data byte into printer 2 D0 Output Data register bit 0 True Carries bit 0 of data byte to printer 3 D1 Output Data register bit 1 True Carries bit 1 of data byte to printer 4 D2 Output Data register bit 2 True Carries bit 2 of data byte to printer 5 D3 Output Data register bit 3 True Carries bit 3 of data byte to printer 6 D4 Output Data register bit 4 True Carries bit 4 of data byte to printer 7 D5 Output Data register bit 5 True Carries bit 5 of data byte to printer 8 D6 Output Data register bit 6 True Carries bit 6 of data byte to printer 9 D7 Output Data register bit 7 True Carries bit 7 of data byte to printer 10 -ACK Input Status register bit 6 True Pulsed low by printer to acknowledge data byte
Rising (usually) edge causes IRQ if enabled11 BUSY Input Status register bit 7 Inverted High indicates printer cannot accept new data 12 NOPAPER Input Status register bit 5 True High indicates printer has run out of paper 13 SELECTED Input Status register bit 4 True High indicates printer is selected and active 14 -AUTOFEED OC/Pullup Control register bit 1 Inverted Low tells printer to line-feed on each carriage return 15 -ERROR Input Status register bit 3 True Pulled low by printer to report an error condition 16 -INITIALIZE OC/Pullup Control register bit 2 True Low tells printer to initialize itself 17 -SELECT OC/Pullup Control register bit 3 Inverted Low tells printer to be selected 18 Ground ... Ground Signal ground (pins 18-25 are all commoned) 25 Ground Transferring Data Via the Parallel Port
The lowest common denominator parallel port is the standard (dumb unidirectional)
type. Data can be transferred between such ports via a PC-to-PC parallel cable
as used with INTERLNK, Laplink and FastLynx, which links
five data outputs from one end to the five status inputs on the other and vice
versa (see below). Data is transferred four bits at a time using the fifth bits
for handshaking. This is known as nibble mode.File Transfer Program Cables
The parallel-to-parallel cable is used by DOS's INTERLNK program.
Laplink and FastLynx cables are the same. The pin-to-pin
connection between two male 25-pin D-sub connectors is: 2-15, 3-13,
4-12, 5-10, 6-11, and the reverse: 15-2, 13-3, 12-4, 10-5, and
11-6, and 25-25. This requires eleven wires. If you have
spare wires, link some extra grounds together. Pins 18 to 25 inclusive are
grounds. A very long cable may be unreliable; limit it to 5 metres,
preferably less.Transferring Data using Standard Parallel Ports
These sample functions use the cable described above and work with any parallel
port. Data is sent four bits at a time, using the fifth lines in each direction
as data strobe and acknowledge respectively. This is sometimes called 'nibble
mode'.--------------------------- snip snip snip ---------------------------
Bidirectional Ports (PS/2 and compatible)
On a bidirectional port, the data register becomes an input port while
input mode is enabled. In this state, the outputs of the buffer that drives
pins 2-9 of the 25-pin connector go into a high-impedance state and these pins
become inputs which may be driven by an external device without stressing or
damaging the driver. Values written to the data register are stored, but not
asserted on the connector. Reading the data register yields the states of the
pins at the time of the access. This allows data to be received (or transferred
between two ports of this type) one byte at a time. This transfer mode is
called byte mode.Sample Program - Display Port Types
This program reports for LPT1, LPT2, and LPT3 whether the port exists and
whether input mode can be enabled by setting the bidirectional control bit in
the control register. This only works on some bidirectional ports, so the
program will report non-bidirectional or in standard mode for ports that
are bidirectional or enhanced, if input mode is not controlled by control
register bit 5.--------------------------- snip snip snip ---------------------------
Name Bidirectional DMA capability Standard ('SPP') No No Bidirectional (PS/2) Yes No EPP (Enhanced Parallel Port) Yes (see below) No ECP (Extended Capabilities Port) Yes (see below) Yes Links
http://www.fapo.com/
Warp 9 Engineering (commercial) home page - technical information
on all port types.