Using a PCI Multi I/O Controller for extending the PC I/O ports
Today's personal computers feature dozens of I/O ports, like USB, RS232, PS/2, Gameport, Parallel Port, SATA, etc. Only a few are interesting for connecting own devices, in particular
- USB, with the advantage of being future-proof, but very complex from the programmer's view
- RS232, with the advantage of having a simple structure and being very old, but still widely-used as an industry standard
- Parallel Port (IEEE 1284), being the only parallel interface but almost died off.
In this article, I'll talk about the parallel port. It features 3 octett registers with
- one bidirectional (tristate) data register
- one status register (4 input bits, one bit capable of interrupt)
- one control register (4 output bits)
So you can use 12 input, 4 output bits or 12 output, 4 input bits, respectively. If you need more I/O pins, you are lost on ordinary PC platforms.
Extending with an PCI Parallel Port controller card
There are multiple vendors that sell those PCI Parallel Port controller cards with one or more parallel ports. I've buyed one of them and built it straight into my linux box:
# lspci 00:0c.0 Communication controller: NetMos Technology PCI 9815 Multi-I/O Controller (rev 01) Subsystem: LSI Logic / Symbios Logic Device 0020 Flags: medium devsel, IRQ 11 I/O ports at 1010 [size=8] I/O ports at 1018 [size=8] I/O ports at 1020 [size=8] I/O ports at 9000 [size=8] I/O ports at 1028 [size=8] I/O ports at 1000 [size=16] Kernel driver in use: parport_pc Kernel modules: parport_pc
Like you see, it offers various I/O ports. After all, there are now two more parallel ports available:
# ls -l /dev/parport* crw-rw---- 1 root lp 99, 0 2009-09-24 17:28 /dev/parport0 crw-rw---- 1 root lp 99, 1 2009-09-24 17:28 /dev/parport1 crw-rw---- 1 root lp 99, 2 2009-09-24 17:28 /dev/parport2
If you take a short look at dmesg (excerpt), you'll notice the capabilities of those ports
# dmesg [ 15.697123] parport_pc 00:09: reported by Plug and Play ACPI [ 15.697352] parport0: PC-style at 0x378 (0x778), irq 7, dma 3 [PCSPP,TRISTATE,COMPAT,EPP,ECP,DMA] [ 15.726365] ACPI: I/O resource piix4_smbus [0xe800-0xe807] conflicts with ACPI region SM00 [0xe800-0xe806] [ 15.726483] ACPI: Device needs an ACPI driver [ 15.726570] piix4_smbus 0000:00:04.3: SMBus Host Controller at 0xe800, revision 0 [ 15.802653] ACPI: PCI Interrupt Link [LNKA] enabled at IRQ 11 [ 15.802749] PCI: setting IRQ 11 as level-triggered [ 15.802767] parport_pc 0000:00:0c.0: PCI INT A -> Link[LNKA] -> GSI 11 (level, low) -> IRQ 11 [ 15.802868] PCI parallel port detected: 9710:9815, I/O at 0x1010(0x1018) [ 15.802916] parport1: PC-style at 0x1010 (0x1018) [PCSPP,TRISTATE] [ 15.915438] input: PC Speaker as /devices/platform/pcspkr/input/input4 [ 15.942662] PCI parallel port detected: 9710:9815, I/O at 0x1020(0x9000) [ 15.942723] parport2: PC-style at 0x1020 (0x9000) [PCSPP,TRISTATE]
The Parallel port driven by the Super I/O port on the mainboard features things like COMPAT, EPP, ECP, DMA modes, while the extended ports only give you the basics like PCSPP, TRISTATE. However, this is enough for ordinary programming (directly accessing the registers without any accleration protocols): All the programs in this project are running on these ports. Since you can use them all together at the same time, you get in total:
- 3 bidirectional registers = 24 I/O, individually tunable tristate or not
- 3 status registers, having totally 12 input bits, thereof 3 interrupt bits
- 3 control registers, having totally 12 output bits
Summing up, we can get at maximum 32 in/out and 12 out/in, respectively. Combining with Linux kernel space programming, that's a powerful setup for only some euros (and you can even buy another PCI controller card to get even more registers) - compared to these very expensive measurement system controllers (above 500 Euros...).