User Mode Drivers

Want to support your device without becoming a kernel hacker? Bryce shows how.
PCI

PCI is this wonderful interface that automatically configures the hardware and automatically assigns the device interrupts and up to six base addresses. You can plug in a card and forget about it--until you need to write the driver. Well fortunately, there's another great cheat to help with this task (drumroll, please): /proc/bus/pci/devices. When you view this file in the /proc pseudo-filesystem, what appears is a bunch of hexadecimal numbers. Here's what my machine says (ignoring the other devices):

0168   148aac05   b   f6400008   f6aff008   00000000
00000000   00000000   00000000   00000000   00400000
00001000   00000000   00000000   00000000   00000000
00000000

For example, I installed a parallel I/O card manufactured by my employer (part number PCI-AC5) into my computer. Looking at this last entry (starting with the 0168), the important fields are the ones that say 148aac05, f6400008 (base address register zero or BAR0) and f6aff008 (BAR1). A vendor and device ID identify each PCI device. The 0x148aac05 indicates this device has a vendor ID of 0x148a (Opto 22) and a device ID of 0xac05. Vendor IDs are managed by the PCISIG organization; Opto 22 chose the specific device ID.

Continuing with the example, the PCI-AC5 I/O card has two configured base address registers (addresses 0xf6400000 and 0xf6aff000). The lowest nibble (least significant four bits) is ignored (set to zero). The least significant bit indicates whether the base address is I/O mapped or memory mapped in the case of x86 architectures. PCI devices may have up to six base addresses and an interrupt (the b in the list). User-mode drivers can't take advantage of the interrupt. A simple fscanf() program can read these values and open the appropriate areas for access.

In the event that you have multiple identical cards, you may find it difficult to know who's who. Do not rely on the order /proc/bus/pci/devices gives compared to the silkscreen slot numbers printed on the motherboard to identify which card is which. To identify the card, I've written applications to toggle some indicators on the cards. This application asks which device index to find and test.

Pitfalls

While user-mode drivers are simple, there are a few shortcomings you should watch out for:

  • Multiple access to the hardware must be made thread safe. That is, two applications or threads cannot randomly share the device unless the hardware itself is not prone to uncoordinated (non-atomic) accesses.

  • Writing to a wrong I/O address may have disastrous effects on the computer or hardware components. I recommend validating the port address arithmetic before attempting a port read or port write. Use some printfs of the I/O addresses before finding out something is wrong.

  • Improper memory accesses as a result of improper pointer arithmetic may freeze the computer. Try some pointer printouts before finding out the hard way. Once the pointer is cast, the most common problem is errors created due to improperly sized pointer arithmetic. Be very careful with pointer arithmetic.

  • While there are mechanisms to determine the size of a PCI base address block, don't rely on them. Determine the actual register locations of the device by locating real hardware documentation. Writing to an undefined location in the allocated block may result in a hard-frozen computer.

Conclusion

If you're thinking about porting that old DOS application, testing out a new hardware device or just want to create a quick-and-dirty hardware application, consider using a user-mode driver. It's ideal for hardware devices that require a simple interface and don't have timing requirements, and it may just help you meet that impossible deadline.

Bryce Nakatani (linux@opto22.com) is an engineer at Opto 22, a manufacturer of automation components in Temecula, California. He specializes in real-time controls, software design, analog and digital design, network architecture and instrumentation.

______________________

Webcast
How to Build an Optimal Hadoop Cluster to Store and Maintain Unlimited Amounts of Data Using Microservers

Realizing the promise of Apache® Hadoop® requires the effective deployment of compute, memory, storage and networking to achieve optimal results. With its flexibility and multitude of options, it is easy to over or under provision the server infrastructure, resulting in poor performance and high TCO. Join us for an in depth, technical discussion with industry experts from leading Hadoop and server companies who will provide insights into the key considerations for designing and deploying an optimal Hadoop cluster.

Learn More

Sponsored by AMD

White Paper
Red Hat White Paper: Using an Open Source Framework to Catch the Bad Guy

Built-in forensics, incident response, and security with Red Hat Enterprise Linux 6

Every security policy provides guidance and requirements for ensuring adequate protection of information and data, as well as high-level technical and administrative security requirements for a system in a given environment. Traditionally, providing security for a system focuses on the confidentiality of the information on it. However, protecting the data integrity and system and data availability is just as important. For example, when processing United States intelligence information, there are three attributes that require protection: confidentiality, integrity, and availability.

Learn more about catching the bad guy in this free white paper.

Learn More

Sponsored by DLT Solutions