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 enabled
11
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.