Driver Design

The first design decision I made was that all of the device drivers should accept the same set of devctl() commands. This meant that to anyone using the device drivers, they'd all look the same. One could argue that sending a "turn on digital bit 1" command to a card that only has analog input doesn't make sense. That's true—in that case, the card simply returns ENOSYS. But the important thing is that we didn't reuse the command number for something else—all cards know about that command, but only some may support it.

The next design decision was that each driver would support one or more cards. This way, instead of having multiple pcl711 drivers running for multiple PCL-711 cards, there'd be only one driver running. Each driver creates multiple mount points under /dev—one for each card. So in a system with three PCL-711 cards and one DIO-144 card (at addresses 0x220, 0x240, 0x260 and 0x280, respectively) you'd see the following devices:


The three PCL-711 devices are managed by the one pcl711 driver, and the one DIO-144 device is managed by the one dio144 driver. At one point I considered having just one mount point for each driver (e.g. /dev/pcl711), instead of multiple mount points, but it turned out to be much easier to consider each device as a separate entity.

You'll notice that we didn't take over /dev/pcl711 as a directory and create the individual devices underneath. This is because the number of devices is limited by the number of ISA slots, which, even in the industrial automation space, is still only a dozen or two. It wasn't worth the extra effort of maintaining a directory hierarchy in the driver.

As mentioned above, all three of the supported cards are ISA cards, so there's no automatic configuration to deal with—whatever you set the I/O port address to on the card is where the card will be. (The one thing that did get me, though, is that on the card's I/O port selector switch, "ON" is a zero and "OFF" is a one. That had me scratching my head for a few hours.)