Overview
The parallel port, also known as the "line printer port", started its career as exactly that: a cheap interface for line printers. Of course, back then, there wasn't any other kind!
As opposed to other computer design approaches, IBM decided to decouple the printer interface from the CPU's physical bus. Instead, they created a simple IO device, following the standard then known as "Centronics interface", traditionally mapped at address 0x378 (or 0x3BC for those equipped with an MDA video card). Additionally, they provided relevant routines through the nowadays obsolete BIOS interrupt 17h.
As time passed, the interface got further enhancements and subsequently got standardised through IEEE, to become what is formally known as the "IEEE 1284". However, the basic functionality still remains intact.
Plugs and numbering
Traditionally, the parallel port is utilised on a plain D-sub-25 female socket at the back of the computer. Consequently, all cables come with a male D-sub-25 plug on one end, with the other end varying between male or female D-sub-25 or male Centronics 36-pin.
The numbering is as follows:


Notice that the pin numbering is reverse on the two sockets. This is very important when making our own cable. Conveniently enough, though, most spare plugs have the pin numbers embossed on the plastic insulator inside the plug itself, saving us the trouble of identifying the pins manually.
Signals
Each pin, naturally, corresponds to a discrete signal. Since the primary use of the parallel port was to communicate with printers, the signals were tailored to serve that functionality.
Below is a table which provides a primary analysis of the signals, along with pin numbers and signal names and logic. Note that a forward slash ( / ) in front of the signal name denotes negative logic.
| Pin # | Signal | Direction | Description | |
![]() |
1 | /STR | OUT | Strobe - data transfer on |
![]() |
2 - 9 | D0 - D7 | OUT | Data lines |
![]() |
10 | /ACK | IN | Printer ready for next character |
![]() |
11 | /BUSY | IN | Printer is busy |
![]() |
12 | PE | IN | Printer out of paper |
![]() |
13 | SLCT | IN | Printer on-line |
![]() |
14 | /AF | OUT | Auto line feed (LF+CD) |
![]() |
15 | /ERROR | IN | Error |
![]() |
16 | INIT | OUT | Initiate printer reset |
![]() |
17 | /SLCT_IN | OUT | Turn printer on-line |
![]() |
18 - 25 | GND | - | Ground lines |
Addresses and registers
The basic implementation of the parallel port organises these signals into three 8-bit registers. Each register has a unique IO address and a name. These three registers, which cover the basic parallel port functionality, occupy three sequential addresses starting from the port's base address.
Here is a bit-wise interpretation of those registers, with the corresponding port pin for each bit. Note that some signals are negative, which means that the function described is activated on "0". Do not confuse this negativity with the previous paragraph's negative signals, where the meaning is that writing a "1" on the register bit will output a "low" at the corresponding pin.
| Data register | ||||||||||||
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||||
| . | . | . | . | . | . | . | . | . | Signal | Pin # | Function | |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
D7 : D0 | 9 : 2 | Data lines | |
| Write only; address = baseaddr; LPT1 address: 0x378 | ||||||||||||
| Status register | ||||||||||||
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||||
| . | . | . | . | . | . | . | . | . | Signal | Pin # | Function | |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
/ERROR | 15 | 0: Error | |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
SLCT | 13 | 1: Printer on-line (selected) | |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
PE | 12 | 1: Printer out of paper | |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
/ACK | 10 | 0: Printer ready for next character | |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
/BUSY | 11 | 0: Printer is busy | |
| Read only; address = baseaddr + 1; LPT1 address: 0x379 | ||||||||||||
| Control register | ||||||||||||
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 | |||||
| . | . | . | . | . | . | . | . | . | Signal | Pin # | Function | |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
/STROBE | 1 | 0: Data transfer on | ||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
/AUTO FEED | 14 | 1: LF plus CD | ||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
/INIT | 16 | 0: Initiate printer reset | ||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
SLCT IN | 17 | 1: Turn printer on-line | ||||
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
IRQ ENABLE | - | 1: Execute interrupt when /ACK=0 | ||||
| Write only; address = baseaddr + 2; LPT1 address: 0x37A | ||||||||||||








